2008-10-02 15 views
18

Biorąc pod uwagę następujących funkcji w bibliotece DLL C:Marszałek "char *" w języku C#

char * GetDir(char* path); 

Jak byś P/Invoke tę funkcję do C# i marszałek char * poprawnie. .NET wydaje się wiedzieć, jak wykonać LPCTSTR, ale kiedy nie mogę wymyślić żadnego marshaling, który nie powoduje wyjątku NotSupportedException przy wywoływaniu tej funkcji.

Odpowiedz

21

Odpowiedź OregonGhost jest poprawna tylko wtedy, gdy znak * zwrócony z GetDir jest przydzielony w HGlobal lub LocalAlloc. Nie pamiętam, który z nich, ale CLR, założy, że każdy typ łańcucha znaków z funkcji PInvoke został przydzielony z jednym lub drugim.

Bardziej niezawodnym sposobem jest wpisanie zwrotu GetDir jako IntPtr. Następnie możesz użyć dowolnej z funkcji Marshal.PtrToStringAnsi, aby uzyskać typ łańcucha. Daje również elastyczność w zakresie uwalniania łańcucha w wybrany przez ciebie sposób.


[DllImport("your.dll", CharSet = CharSet.Ansi)] 
IntPtr GetDir(StringBuilder path); 

Czy możesz podać nam inne wskazówki dotyczące zachowania GetDir? Czy modyfikuje ciąg wejściowy? W jaki sposób zwracana jest wartość zwracana? Jeśli możesz zapewnić, że mogę dać znacznie lepszą odpowiedź.

+0

Ahhhh .... PtrToStringAnsi było tym, czego szukałem, w międzyczasie zorientowałem się, że używam IntPtr, ale teraz napotkam jeden szkopuł ... Używam .NETCF i PtrToStringAnsi jest tylko w pełnym frameworku :( –

+0

Okazuje się, że OpenNetCF ma PtrToStringAnsi .... wygląda jak problem został rozwiązany, oznaczy to jako zaakceptowany, gdy tylko będę mógł przetestować kod –

+0

.NET .NET automatycznie rozpoznaje StringBuilder na znak * dla parametrów wejściowych lub był potrzebujesz jakiejś biblioteki innej firmy, aby to zadziałało? Dzięki. – kmehta

12

Spróbuj

[DllImport("your.dll", CharSet = CharSet.Ansi)] 
string GetDir(StringBuilder path); 

łańcuch jest automatycznie przetaczane do zera zakończony sznurkiem i z właściwością CharSet, powiesz naziemnego, że powinien użyć ANSI zamiast Unicode. Uwaga: Użyj ciąg (lub System.String) dla const char *, ale StringBuilder dla znaku *.

Możesz także wypróbować MarshalAs, jak w this example.

+2

Czy znasz jakieś powody, dla których 'string ansi = Marshal.PtrToStringAnsi (ptr);' zakończyłoby się sukcesem, ale zwrócenie 'string' z' CharSet = CharSet.Ansi' zakończyłoby się niepowodzeniem? – jocull