使用c#访问c++dll中带有char*参数的函数时发生AccessViolationException

AccessViolationException when accessing function with char * argument in c++ dll with C#

本文关键字:函数 参数 AccessViolationException char 访问 c++dll 使用      更新时间:2023-10-16

问题尝试使用以下原型的c++dll中的函数。。。

int connectDfuBootloader(char * usbIndex) 

从C#,使用这些P/Invoke签名中的任何一个,都会导致AccessViolationException:

  1. IntPtr
[DllImport(@"CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int connectDfuBootloader(IntPtr usbIndex);
public static int connectDfuBootloader(string usbIndex)
{            
IntPtr value = Marshal.StringToHGlobalAuto(usbIndex);
return connectDfuBootloader(value);
}       
  1. 字符串
[DllImport(@"CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int connectDfuBootloader(string usbIndex);
  1. StringBuilder
[DllImport(@"CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int connectDfuBootloader(StringBuilder usbIndex);
  1. 马歇尔主题变奏曲,尝试LPStr、LPTStr等
[DllImport(@"CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int connectDfuBootloader([MarshalAs(UnmanagedType.LPStr)]string usbIndex);
  1. 指定字符集、ANSI、Unicode等主题的变体
[DllImport(@"CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl, CharSet =CharSet.Ansi)]
public static extern int connectDfuBootloader(string usbIndex);

有人能提出什么建议吗?

我尝试过的其他东西

各种StackOverflow帖子,例如使用C#访问非托管C++DLL时发生AccessViolationException

此外,出于测试目的,我尝试制作自己的小型C++dll,其中包含一个与上面的问题具有相同签名的函数:

int functionAlpha(char * a)
{   
if (a[0] == 'a')
return 10;
else
return 20;
}

我可以使用上面的任何方法,例如,毫无问题地从C#访问这个功能

[DllImport(@"test.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int functionAlpha(string a);

这让我觉得"int connectDfuBootloader(char*usbIndex("函数有一些特别之处。但他们有相同的签名,为什么一个有效,另一个无效?我没有dll的源代码,所以不能在那里查看是否有任何其他差异。

更新-按照@Taekahn下面的建议,尝试了C++/CLI包装,同样的事情

因此,我在C++/CLI包装器项目的标题中有这样的内容:

#include "include/CubeProgrammer_API.h"
using namespace System;
namespace CLI
{
public ref class CubeWrapper
{
public:        
int wrappedConnectDfuBootloader(String^ a);
};
}

然后在包装器项目中的一个cpp文件中,我有:

namespace CLI
{
static char* string_to_ncchar_array(String^ string)
{
char* str = (char*)(Marshal::StringToHGlobalAnsi(string)).ToPointer();
return str;
}
int CubeWrapper::wrappedConnectDfuBootloader(String^ a)
{        
a = "USB0";
// Calls the function from the linked c++ dll I'm trying to wrap
return connectDfuBootloader(string_to_ncchar_array(a));        
}
}

它给出了相同的结果,System.AccessViolationException!这里可能发生了什么?

还尝试使用c++中的dll尝试使用c++应用程序中的dll执行相同的操作序列,效果良好。

原来dxiv是正确的;查看了API提供的一些c++示例代码,发现必须首先设置几个回调。一旦我整理了这些,问题就解决了。