p/invoke calling C dll from c#

妖精的绣舞 提交于 2019-12-23 05:35:09

问题


this is my C code

extern "C"
{ 
     __declspec(dllexport) void DisplayHelloFromDLL(string a)
   {    
     printf ("%s\n",a)
   }
}

this is my C# code

class HelloWorld
{
    [DllImport("TestLib.dll")]
    public static extern void DisplayHelloFromDLL(string a);

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

It built successfully but crash like this:

SO,how to use P/invoke to call my own C dll from C#? Please help,thanx in advance.


回答1:


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++.

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);
}

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.

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.




回答2:


Please take a look at marshalling string at MSDN

In a nut shell, a C# string doesn't get marshalled as std::string but a char* by default




回答3:


For one thing the return type is not matching. In C it is void and in C# int.




回答4:


Change your C++ param type to char* and update your C# code as following

class HelloWorld
{
  [DllImport("TestLib.dll")]
  public static extern void DisplayHelloFromDLL(IntPtr a);

  static void Main ()
  {
    string a = "Hello";
    var ptr = System.Runtime.Marshal.StringToHGlobalAnsi(a);
    DisplayHelloFromDLL(ptr);
    System.Runtime.Marshal.FreeHGlobal(ptr);
  }
}


来源:https://stackoverflow.com/questions/8891528/p-invoke-calling-c-dll-from-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!