我已经提供了一个由C#调用的DLL。 DLL包含两个方法如下
extern "C" {
__declspec(dllexport) BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
}
BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr) {
CString strResult = "";
char* sz;
::SetVars(bDiagErr, bProcErr);
if (sz = ::GroupInit((char*)bstrIniFile, 1))
strResult = sz;
return strResult.AllocSysString();
}
我试图通过首先定义类来调用C#中的这些DLL:
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
string strCmdFile,
bool bAllowBadDiagCodes,
bool bAllowBadProcCodes
);
并且正在做
this.strCommandFilePath = "C:\\MyDir\\MyCommandFile.txt";
string s = Grouper.GrouperServer.GroupInit(this.strCommandFilePath, true, true);
但DLL返回错误:'找不到命令文件:" C"' (仅在路径的第一个字符,我在C ++ DLL中检查过)。由于某种原因,字符串this.strCommandFilePath
未正确传递给C ++方法。
上述电话有什么问题?
修改以发表评论。
if (sz = ::GroupInit((char*)bstrIniFile, 1))
语句中调用的方法在.c文件中定义并具有签名
char *GroupInit(char *szCmd, int iType)
{
...
}
答案 0 :(得分:1)
在此处使用TCHAR
及相关类型是错误的。 TCHAR
的用例是针对需要为没有Unicode支持的Windows 9x和Windows NT进行编译的代码。那些日子早已过去,TCHAR
掩盖了这个问题。更重要的是,底层代码使用char*
,因此假装您的包装器代码可以执行任何其他操作是没有意义的。所以切换到char
。
最重要的是你要扔掉const。我想因为你调用的函数接受一个不可修改的参数的可修改缓冲区。最佳解决方案是修复错误接受char*
的原始库代码并使其接受const char*
。如果你不能这样做那么你需要抛弃const。但是用const_cast<>
做C ++方式。
所以,我有这样的C ++代码:
BSTR GroupInit(const char* szIniFile, bool bDiagErr, bool bProcErr) {
CString strResult = "";
char* sz;
::SetVars(bDiagErr, bProcErr);
if (sz = ::GroupInit(const_cast<char*>(szIniFile), 1))
strResult = sz;
return strResult.AllocSysString();
}
C#代码应为:
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
string strCmdFile,
bool bAllowBadDiagCodes,
bool bAllowBadProcCodes
);
现在,人们想知道sz
会发生什么。谁应该解除分配呢?它甚至需要被解除分配吗?只有你能回答这些问题。