p /调用从c#调用C dll

时间:2012-01-17 08:19:09

标签: c# c dll pinvoke

这是我的C代码

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

这是我的C#代码

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

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

它构建成功,但崩溃如下:

Debug http://i44.tinypic.com/1qr9sj.jpg

那么,如何使用P / invoke从C#调用我自己的C dll? 请提前帮助,而不是。

4 个答案:

答案 0 :(得分:2)

请查看marshalling string at MSDN

在坚果壳中,C#字符串不会被编组为std::string,而是默认为char*

答案 1 :(得分:2)

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

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

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

.net string的默认p / invoke编组是将char*作为[In]参数传递。根据其他答案之一的建议,不需要IntPtrStringToHGlobalAnsiFreeHGlobal的复杂性。如果你可以让p / invoke marshaller完成这项工作,那么最好这样做。

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

答案 2 :(得分:1)

一方面,返回类型不匹配。在C中,它是void,在C#int

答案 3 :(得分:1)

将您的C ++ param类型更改为char *并按以下步骤更新您的C#代码

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