使用来自C ++ dll的__declspec(dllexport)签名声明来调用C#

时间:2010-12-24 07:13:12

标签: c# c++ visual-studio-2010

我试图调用C ++ dll中声明为__declspec(dllexport)的方法在C#中使用,但我不知道如何从C ++返回字符串值以及如何使用DllImport声明签名在C#。

C ++代码“VNVAPI.dll”

  __declspec(dllexport) char * GetGpuName(int phyGPUid)
  {
      CNvidia * pInstance = CNvidia::GetInstance();
      char  szName[512]={0};
      pInstance->GetGpuName(phyGPUid,szName,512);
      return szName;
  }

C#方法签名:

[DllImport("VNVAPI.dll")]
   public static extern  char GetGpuName(int phyGPUid);

生成错误:

  

调用PInvoke函数   '核心!Core.Hardware.IO.NVAPI :: GetGpuName'   堆栈不平衡。这是   可能是因为管理的PInvoke   签名与非托管不匹配   目标签名。检查一下   调用约定和参数   PInvoke签名与目标匹配   非托管签名。

感谢。

3 个答案:

答案 0 :(得分:2)

正如其他人所指出的那样,您需要在P / Invoke中指定C调用约定,并使用托管端的字符串来封送空终止的char *。

但是,您应该重新调整C ++例程以将char *作为输入参数以及缓冲区长度参数。然后,您可以在本机代码中写入此缓冲区。这避免了当前问题,即当前您拥有代码的数据是从堆栈返回的,当然,当函数返回时,它会被展开。

使用static的建议会使这个内存全局化,从而避免堆栈展开问题,但代价是线程安全。是的,它可能适用于这个用例,但这是一个不好的习惯。

答案 1 :(得分:0)

错误消息可能令人困惑。

不详细说明,试试这个:

static char  szName[512]={0};

如果仍然出现错误,则需要在DllImport属性中指定调用约定。

编辑:

还为C#方法声明生成返回类型string

答案 2 :(得分:0)

错误消息建议检查调用约定。我怀疑该函数正在使用C调用约定,这将解释不平衡堆栈。我建议您在DllImport属性中指定调用约定(如@leppi建议的那样)。像这样:

[DllImport("VNVAPI.dll", CallingConvention=CallingConvention.Cdecl)]

根据Strings samples,返回值应为string

static extern string GetGpuName(int phyGPUid);