Hallo,
Ich habe ein Problem beim einbinden einer in Visual eMbedded C++ geschriebenen Dll.
In dieser Dll gibt es eine Funktion, die einen BSTR* als Argument nimmt. In diesen BSTR* wird dann ein String geschrieben. Wenn ich nun jedoch einen IntPtr übergebe und diesen dann mit Marshal.PtrToStringUni konvertiere und ihn in einer MessageBox anzeigen lasse, dann kommt nur Müll raus.
C++ Code
int test(BSTR *test)
...
test = (BSTR*)"test";
...
C# Code
[DllImport("test.dll", EntryPoint="test")]
public static extern int test(ref IntPtr test);
weiter unten dann
IntPtr t = new IntPtr(0);
int ret = test(ref t);
MessageBox.Show(Marshal.PtrToStringUni(t));
In der MessageBox wird nun nur wirres zeug angezeigt. Erst dachte ich es hätte irgendwas mit Unicode/ASCII etc zu tun, aber egal wie ich den String auch änder, die MessageBox zeigt immer dasselbe an.
Vielen Dank im Vorraus
TheWizzard
Hi Wizzard,
und warum definierst du nicht
[DllImport("test.dll", EntryPoint="test")]
public static extern int test( string test);
?
Ansonsten gibt es schon viele Threads zu übergabe an DLL Funktionen.
Detlef
BStrings sind zwar Unicode, allerdings mit Längenpräfix. Mit PtrToStringUni() kommst du dan nicht weiter. Du müßtest PtrToStringBStr() verwenden, aber das wird vom CF nicht unterstützt.
Theoretisch gäbe es da noch das MarshalAs-Attribute "BStr", das wird sogar vom CF unterstützt, aber die Klasse MarshalAS selbst nicht (selten bescheuerte Doku!).
Im CF 1.0 ist nichts eingebaut mit dem du Bstr wandeln kannst (daher auch keine COM-Anbindung). Ab 2.0 gibt es sowohl PtrToStringBStr() als auch MarshalAs.BStr.
Alternativ kann du eine Freeware-Bib verwenden:
http://www.inthehand.com/CategoryView,category,Downloads.aspx
Hier gibt es ComMarshal.PtrToStringBSTR()
@deti61: Hab ich auch schon probiert, selbes Problem.
@svenson: Hab mich auch schon geärgert das es da MarshalAs nicht gibt. Werd mir mal die Bibliothek angucken.
*EDIT*
Hab grad gesehen, dass die Bibliothek nur für nicht-kommerzielle Zwecke kostenlos ist. Kann man nicht manuell in einem unsafe Block die kovertierung machen? Ich werd mal gucken, ob Google dazu was ausspuckt.
Danke
TheWizzard
Hmmm
Mit .net 2.0 scheint das ja alles wunderbar zu funktionieren. Wie stabil ist denn die beta 2? Irgendwelche erfahrungen? Und ist eigentlich bekannt, wann die finale .Net 2.0 version rauskommt?
MfG
TheWizzard
Hier mal ein Stück Code aus einer Newsgroup:
How about replacing it with the following code:
int nLen = SysStringLen(ptr) ' Needs to be pinvoked
Dim buffer() as Byte = new Byte(nLen * 2) ' or whatever VB syntax is
Marshal.Copy(ptr, buffer, 0, nLen * 2)
str = Encoding.Unicode.GetString(buffer)
I suggest that you also carefully check the nLen value there to see that
it's reasonable
SysStringLen() muss du via DLLImport einbinden. Die fehlende Null-Terminierung verkraftet GetString() offenbar wegen der bekannten Länge des Byte-Arrays.
SysStringLen wird zwar einwandfrei aufgerufen, gibt aber eine riesige Zahl zurück, und daher gibt es dann eine OutOfMemoryException. Hab schon bei google gesucht, konnte aber nichts dazu finden. Vielleicht sollte ich wirklich auf .Net 2.0 migrieren, allerdings stört mich irgendwie der beta status.