根据我对供应商文档的解释,我已将解决方案中的所有内容编译为x86或x64,具体取决于目标平台.供应商提供了专有DLL的32位和64位版本,并且我确保我为给定的构建使用正确的版本.我的机器是32位的.在我的机器上,在发布版本或调试版本中测试我的应用程序的x86版本似乎工作正常.但是,在64位上,应用程序在调试模式下工作,但在发布模式下出现System.AccessViolationException失败.
我已经阅读了this nice blog entry,似乎很好地描述了调试与发布问题,以及引发博客文章的this question and answer.但是,我不确定如何在这种情况下解决问题.
AccessViolationException似乎是在第一次从C包装器返回(或尝试返回)任何实际长度的字符串时发生的.这是违规的C#代码:
// In one file of the C# wrapper:
public string GetKey()
{
// swigCPtr is a HandleRef to an object already created
string ret = csWrapperPINVOKE.mdMUHybrid_GetKey(swigCPtr);
return ret;
}
// In the csWrapperPINVOKE class in another file in the C# wrapper:
[DllImport("csWrapper.dll",EntryPoint="CSharp_mdMUHybrid_GetKey")]
public static extern StringBuilder mdMUHybrid_GetKey(HandleRef jarg1);
来自C包装器的麻烦的C代码:
SWIGEXPORT char * SWIGSTDCALL CSharp_mdMUHybrid_GetKey(void * jarg1) {
char * jresult ;
mdMUHybrid *arg1 = (mdMUHybrid *) 0 ;
char *result = 0 ;
arg1 = (mdMUHybrid *)jarg1;
result = (char *)(arg1)->GetKey();
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT已被定义为__declspec(dllexport).在调试中,我发现了SWIG_csharp_string_callback,定义为:
/* Callback for returning strings to C# without leaking memory */ typedef char * (SWIGSTDCALL* SWIG_CSharpStringHelperCallback)(const char *); static SWIG_CSharpStringHelperCallback SWIG_csharp_string_callback = NULL;
被设置为委托(在C#包装器中):
static string CreateString(string cString) {
return cString;
}
我试过搞乱这段代码来使用Marshal.PtrToStringAut这样的结构无济于事.如何解决和/或解决此问题?
通常的方法是使用LocalAlloc分配内存,然后可以使用Marshal.FreeHGlobal从托管代码中释放内存.这样您就不再需要(kludgy且显然无功能)SWIG_csharp_string_callback和CreateString.
C代码:
SWIGEXPORT HLOCAL SWIGSTDCALL CSharp_mdMUHybrid_GetKey(mdMUHybrid* jarg1)
{
char const* const str = jarg1->GetKey();
std::size_t const len = std::strlen(str);
HLOCAL const result = ::LocalAlloc(LPTR,len + 1u);
if (result)
std::strncpy(static_cast<char*>(result),str,len);
return result;
}
C#代码:
// In one file of the C# wrapper:
public string GetKey()
{
return csWrapperPINVOKE.mdMUHybrid_GetKey(swigCPtr);
}
// ...
public static class csWrapperPINVOKE
{
// ...
[DllImport("csWrapper.dll")]
private static extern IntPtr CSharp_mdMUHybrid_GetKey(HandleRef jarg1);
public static string mdMUHybrid_GetKey(HandleRef jarg1)
{
var ptr = CSharp_mdMUHybrid_GetKey(jarg1);
try
{
return Marshal.PtrToStringAnsi(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
顺便说一句,你展示的那段微小的C代码片段是一个可怕的C-with-classes遗物;如果这是代码库其余部分的代表,那么,哇……: – /