[英]C DLL does NOT Work in C# but Does work in C++
I don`t understand this code below, that it is working with my c++ but it just does not want to work with c#. 我不明白下面的这段代码,它可以与我的c ++一起工作,但是它只是不想与c#一起工作。 Can you please help me to understand what is wrong here and i think i have to say that i am absolutely new to C#. 您能帮我了解这里有什么问题吗,我想我必须说我对C#绝对陌生。
My_Lib.h
extern "C" __declspec(dllexport) void __cdecl get(char** buffer);
My_lib.c
void get(char** buffer)
{
*buffer = (char*)calloc(6, sizeof(char));
assert(*buffer);
buffer[5] = '\0';
*buffer = "Hello";
}
in my C#-----> 在我的C#----->
public static class NativeMethods
{
[DllImport("My_C_Lib.dll", CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern void get(char** buffer);
}
//////////////////// Main()///////
unsafe
{
char* my_buf;
NativeMethods.get(&my_buf);
string s = new string(my_buf);
Console.WriteLine(s);
}
NOTE: Actually my DLL does Work when i call this c function from c++ but as i said above NOT in C#, there is no Errors but string s variable in C# prints some undefined sibols, but DLL "works" thanks in advance!!! 注意:实际上,当我从c ++调用此c函数时,我的DLL确实可以工作,但是正如我在C#中上面所说的那样,没有错误,但是C#中的string s变量会打印一些未定义的sibol,但是DLL是“有效的”,谢谢!!!
The code is nearly correct, but... 该代码几乎是正确的,但是...
C DLL does NOT Work in C# but Does work in C++ C DLL在C#中不起作用,但在C ++中起作用
In C and C++ char
is a 8-bit data type. 在C和C ++中, char
是8位数据类型。 In C# char
is a 16-bit data type. 在C#中, char
是16位数据类型。
This means that C# expects that the pointer returned by the get()
function is expected to be a "wide string", while in C++ expects an "ANSI string". 这意味着C#期望由get()
函数返回的指针应为“宽字符串”,而在C ++中则应为“ ANSI字符串”。
I simply changed one single line in your program: 我只是在程序中更改了一行:
*buffer = "H\0e\0l\0l\0o\0\0\0";
... and it works! ...而且有效!
You may of course also use the "wide string" functions of the modern C compilers: 您当然也可以使用现代C编译器的“宽字符串”功能:
void get(wchar_t** buffer)
{
*buffer = L"Hello";
}
By the way 顺便说说
There is another error in your program: 您的程序中还有另一个错误:
*buffer = (char*)calloc(6, sizeof(char));
...
*buffer = "Hello";
This makes no sense: 这没有任何意义:
The second line ( *buffer = "Hello";
) will not copy the string to the memory allocated by calloc
, but it will write the address of the string "Hello"
to the variable buffer
and the value (address) returned by calloc
is overwritten (and lost). 第二行( *buffer = "Hello";
) 不会将字符串复制到calloc
分配的内存中,但是会将字符串"Hello"
的地址写入变量buffer
并且calloc
返回的值(地址)为被覆盖(丢失)。
Your best bet is to change the PInvoke signature of your C function to taking a ref IntPtr
: 最好的选择是将C函数的PInvoke签名更改为ref IntPtr
:
[DllImport("My_C_Lib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void get(ref IntPtr buffer);
To call this, you'll need to instantiate an IntPtr and pass it by reference to the C function (this is analagous to declaring a char *
in C and passing it by address): 要调用此方法,您需要实例化一个IntPtr并将其通过引用传递给C函数(这类似于在C中声明一个char *
并通过地址传递它):
IntPtr ptr;
get(ref ptr);
// ptr is now an unmanaged pointer to the allocated string
Now, you need to convert the pointed-to string to a managed string
. 现在,您需要将指向的字符串转换为托管string
。 To do this you must make a copy of the string. 为此,您必须复制字符串。
string str = Marshal.PtrToStringAnsi(ptr);
PtrToString...()
variant. 确保了解ANSI和Unicode字符串之间的区别,并确保调用适当的PtrToString...()
变体。 ptr
for you since it was allocated by unmanaged code. 请注意, .NET运行时不会为您管理分配的ptr
,因为它是由非托管代码分配的。 You must free it yourself using whatever the appropriate mechanism is for your DLL (ideally, the DLL should provide a corresponding free function since it is the one who allocated the memory in the first place). 您必须使用适用于DLL的适当机制自己释放它(理想情况下,DLL应该提供相应的释放功能,因为它首先是分配内存的那个)。 get()
succeeded and that ptr
is not IntPtr.Zero
. 确保get()
成功,并且ptr
不是IntPtr.Zero
。 get()
returns and the time you free the pointer, the try/finally
construct is your friend. 为避免泄漏,如果在get()
返回时间与释放指针的时间之间任何代码都可能引发异常,则try/finally
构造是您的朋友。 (Aside: Note that get
is a Contextual Keyword in C# and thus while you can use it as an identifier, you may prefer not to in order to avoid confusion.) (此外:请注意, get
是C#中的上下文关键字 ,因此尽管可以将其用作标识符,但为了避免混淆,您可能不希望这样做。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.