Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 字符串参数未正确编组到C++;动态链接库_C#_C++_Parameters_Pinvoke - Fatal编程技术网

C# 字符串参数未正确编组到C++;动态链接库

C# 字符串参数未正确编组到C++;动态链接库,c#,c++,parameters,pinvoke,C#,C++,Parameters,Pinvoke,我已经被提供了一个由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;

我已经被提供了一个由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++中检查过的路径的第一个字符)。由于某种原因,字符串<代码> .StrutdReMePATAs< /C> >没有被正确地传递到C++方法中。 上述通话有什么问题?


编辑以处理评论

if(sz=::GroupInit((char*)bstrIniFile,1))语句中调用的方法在.c文件中定义并具有签名

char *GroupInit(char *szCmd, int iType)
{
   ...
}

在此处使用
TCHAR
和相关类型是错误的。
TCHAR
的用例用于需要为不支持Unicode的Windows 9x和支持Unicode的Windows NT编译的代码。那些日子早已过去,
TCHAR
正在掩盖问题。此外,底层代码使用
char*
,因此假装包装器代码可以做任何其他事情都没有意义。因此,切换到
char

最重要的是,你正在抛弃康斯特。我猜是因为您调用的函数接受一个可修改的缓冲区,用于它不修改的参数。最好的解决方案是修复错误地接受
char*
的原始库代码,并使其接受
const char*
。如果你不能做到这一点,那么你需要扔掉常量。但是C++的方式是用<代码> COSTOSTCAST < < /P> <>所以,我会有这样的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();
}

现在,我们想知道
sz
会发生什么。谁会被期望解除分配呢?它甚至需要被解除分配吗?只有你才能回答这些问题。

你这里一团糟。出于某种原因,您正在使用
TCHAR
。你为什么这么做?您确实需要确定正在使用的字符集
TCHAR
会让您感到困惑,根本不会给您带来任何好处。我也非常怀疑这个演员。你为什么这么做?另外,你100%确定你发布了真实的代码吗?您确定p/invoke中没有
CharSet.Unicode
吗?您好,大卫,不幸的是,我刚刚继承了这个损坏的代码。我不知道是谁写的。我只是想让底层C代码能够(快速)从C#调用。所以我把旧的C++包装代码(写为COM库),你在代码> GROUP PNIT 方法中看到的东西,并把它放在我的“包装器方法”里面。我没有改变以前的类型。我有旧的C++包装代码和底层C代码,所以可以改变类型,但是另一个要求是这个C++代码可以在Linux的盒子上运行(还没有完成这个部分!),这并没有什么帮助。您需要了解什么是
TCHAR
。以及你为什么要这样做。你说的
TCHAR
是指使用
LPCTSTR
;嗯,我相信这是你需要为不同的C++编译器做互操作的。我不是C++开发者,所以我承认我在这里挣扎,为什么要做的事情,当它完成了。我很高兴看到改变的类型,但我需要再次与许多不同的C++编译器,所以我不知道这里需要什么。就
GroupInit(…)
方法中的代码而言,我确信它是可以更改的,因为我不知道为什么要进行转换,甚至不知道如果
是按原样使用的话为什么要进行
。。注意,之所以要进行字符转换,是因为
::GroupInit
调用调用的是一个C方法,它采用
字符*
。我们正在寻找重写整个东西,但要通过今年我必须启用从.NET使用。我讨厌这种垃圾,但我别无选择。
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl,
    CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
    string strCmdFile, 
    bool bAllowBadDiagCodes, 
    bool bAllowBadProcCodes
);