简体   繁体   English

从C ++ dll使用__declspec(dllexport)签名声明以在C#中调用时出现问题

[英]Issue using __declspec(dllexport) signature declaration from C++ dll to call in C#

I´m trying to call a method that is in a C++ dll declarated as __declspec(dllexport) to use in C#, but I don´t know how to return a string value from C++ and how to declare the signature using DllImport in C#. 我正在尝试调用在C ++ dll中声明为__declspec(dllexport)的方法以在C#中使用,但是我不知道如何从C ++返回字符串值以及如何在C#中使用DllImport声明签名。

C++ code "VNVAPI.dll" 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# method signature: C#方法签名:

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

Error generated: 生成错误:

A call to PInvoke function 'Core!Core.Hardware.IO.NVAPI::GetGpuName' has unbalanced the stack. 对PInvoke函数'Core!Core.Hardware.IO.NVAPI :: GetGpuName'的调用已使堆栈不平衡。 This is likely because the managed PInvoke signature does not match the unmanaged target signature. 这很可能是因为托管PInvoke签名与非托管目标签名不匹配。 Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature. 检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

Thanks. 谢谢。

As has been pointed out by others you need to specify the C calling convention in your P/Invoke and also use string on the managed side to marshal the null terminated char*. 正如其他人指出的那样,您需要在P / Invoke中指定C调用约定,并在托管端使用字符串来编组以null结尾的char *。

However you should rejig the C++ routine to take a char* as an input parameter, together with a buffer length parameter. 但是,您应该重新调整C ++例程以将char *与缓冲区长度参数一起作为输入参数。 You then write into this buffer in the native code. 然后,您可以在本机代码中写入此缓冲区。 This avoids the current problem that the data, as you presently have the code, is returned from the stack which, of course, is unwound as the function returns. 这避免了当前的问题,即您当前具有代码的数据是从堆栈中返回的,而堆栈当然会在函数返回时解开。

The suggestion to use static will make this memory global and so avoid stack unwind problems, at the expense of thread safety. 使用静态的建议将使该内存成为全局内存,从而避免堆栈展开问题,但以线程安全为代价。 Yes it will likely work for this use case but its a bad habit to get into. 是的,它可能适用于此用例,但是这是一个坏习惯。

The error message might be confusing. 错误消息可能会令人困惑。

Without going into detail, try this: 没有详细说明,试试这个:

static char  szName[512]={0};

If you still get the error, the you need to specify the calling convention in the DllImport attribute. 如果仍然出现错误,则需要在DllImport属性中指定调用约定。

Edit: 编辑:

Also make the return type string for C# method declaration. 还为C#方法声明创建返回类型string

The error message suggests checking the calling convention. 错误消息建议检查调用约定。 I suspect that the function is using C calling convention, which would explain the unbalanced stack. 我怀疑该函数正在使用C调用约定,这将解释不平衡堆栈。 I would suggest that you specify the calling convention (as @leppi suggested) in your DllImport attribute. 我建议您在DllImport属性中指定调用约定(如@leppi建议的那样)。 Like this: 像这样:

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

According to the Strings samples , the return value should be string : 根据Strings样本 ,返回值应为string

static extern string GetGpuName(int phyGPUid);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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