且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

p / invoke调用c dll从c#

更新时间:2021-11-02 23:31:45

首先你的代码是C ++而不是C.你的函数接收类型为 std :: string 的参数和使用 std :: string 意味着您的代码实际上是C ++。

First of all your code is C++ rather than C. Your function receives a parameter of type std::string and the use of std::string means that your code is actually C++.

现在,此参数类型是您问题的根源。您不能在.net中创建 std :: string ,而需要使用 char * 来传递字符串数据。以下代码是您需要的:

Now this parameter type is the root of your problem. You cannot create a std::string in .net and instead will need to use a char* to pass the string data. The following code is what you need:

C ++

__declspec(dllexport) void DisplayHelloFromDLL(char* a)
{    
    printf("%s\n", a);
}

C#

[DllImport("TestLib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void DisplayHelloFromDLL(string a);

static void Main ()
{
    string a = "Hello";
    DisplayHelloFromDLL(a);
}

默认的p / invoke编组为.net 字符串是将 char * 作为 [In] 参数传递。不需要复杂的 IntPtr StringToHGlobalAnsi FreeHGlobal 如其他答案之一所建议的。如果可以让p / invoke marshaller做这个工作,那么***这样做。

The default p/invoke marshalling for a .net string is to pass a char* as an [In] parameter. There is no need for the complexity of IntPtr, StringToHGlobalAnsi, FreeHGlobal as suggested by one of the other answers. If you can let the p/invoke marshaller do the work then it is preferable to do so.

请注意,您还需要确保您的呼叫约定相符。假设您在构建C ++代码时没有使用任何特殊的编译器选项,该代码将默认使用 cdecl 调用约定。您可以使用 CallingConvention 参数与 DllImport 属性进行匹配。

Note that you also need to make sure that your calling conventions match. Under the assumption that you have not used any special compiler options when building your C++ code, that code will default to used cdecl calling convention. You can make that match with the CallingConvention parameter to the DllImport attribute.