我在dll中有这些功能:
DWORD getTypes(const char* const i_formName, const char* const i_fieldName, wchar_t*** i_output, int* i_size)
{
try
{
std::vector<std::wstring> i_temp;
multilanguage.getTypes(i_formName, i_fieldName, i_temp);
*i_size = i_temp.size();
*i_output = new wchar_t *[*i_size];
for (int i = 0; i < *i_size; ++i)
{
*i_output[i] = new wchar_t[i_temp[i].length() + 1];
wcscpy_s(*i_output[i], i_temp[i].length() + 1, i_temp[i].c_str());
}
return 0;
}
catch (MultilanguageException & e)
{
return e.getErr();
}
}
void FreeString(wchar_t ** i_output)
{
if (NULL != (*i_output))
delete[](*i_output);
}
这些函数有效,因为如果我在C ++程序中使用它们,我会得到预期的结果。
不幸的是我需要从C#程序中调用这些函数。我用以下方式包装了这些函数:
[DllImport("multilanguage_c.dll", EntryPoint = "getTypes", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 _getTypes([In] string i_formName,
[In] string i_fieldName,
out IntPtr i_output, ref int size);
[DllImport("multilanguage_c.dll", EntryPoint = "FreeString", CallingConvention = CallingConvention.Cdecl)]
private static extern void _FreeString(ref IntPtr i_output);
static public string[] getTypes(string i_formName, string i_fieldName)
{
IntPtr i_result = IntPtr.Zero;
int size = 0;
IntPtr stringSize = IntPtr.Zero;
UInt32 err = _getTypes(i_formName, i_fieldName, out i_result, ref size);
if (0 != err)
{
ExceptionHandler.ExcpetionThrower(err);
}
string[] ManagedStrArray = null;
MarshalUnmananagedStrArray2ManagedStrArray(i_result, size, out ManagedStrArray);
return ManagedStrArray;
}
static private void MarshalUnmananagedStrArray2ManagedStrArray(IntPtr pUnmanagedStringArray, // Pointer to an array of unmanaged WCHAR pointers.
int StringCount, // The total number of WCHAR*s in pUnmanagedStringArray.
out string[] ManagedStringArray // Receipient of the array of managed strings.
)
{
// First allocate an array of IntPtrs.
IntPtr[] pIntPtrArray = new IntPtr[StringCount];
// Also allocate an array of managed strings using
// the ManagedStringArray parameter.
ManagedStringArray = new string[StringCount];
// Copy the WCHAR*s from pUnmanagedStringArray to
// the array of IntPtrs (pIntPtrArray).
Marshal.Copy(pUnmanagedStringArray, pIntPtrArray, 0, StringCount);
// Then, one by one, convert each of the WCHAR*s
// inside the pIntPtrArray array into a managed string.
for (int i = 0; i < StringCount; i++)
{
ManagedStringArray[i] = Marshal.PtrToStringAuto(pIntPtrArray[i]);
_FreeString(ref pIntPtrArray[i]);
}
// Finally, free the entire buffer of unmanaged
// WCHAR*s.
_FreeString(ref pUnmanagedStringArray);
}
在函数MarshalUnmananagedStrArray2ManagedStrArray
中,如果StringCount
大于1,则在ManagedStringArray[i] = Marshal.PtrToStringAuto(pIntPtrArray[i]);
的第二次尝试时,我会收到以下异常:
未处理的类型&#39; System.AccessViolationException&#39;发生在mscorlib.dll
我还试着评论_FreeString(ref pIntPtrArray[i]);
行,认为_FreeString
函数做错了什么但没有任何改变。非常感谢任何帮助!