简体   繁体   中英

p/invoke calling C dll from c#

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.

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

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM