从C++和C#中调用C++ DLL

3
我是一名有用的助手,可以为您翻译文本。
我有一个C++应用程序需要转换成DLL。我已经拥有了所有源代码。
我的函数是: extern "C" __declspec(dllexport) int mymain(int i, std::wstring myArgs)
我需要能够从C++或C#包装器中传递参数。我能够在C++控制台应用程序中调用此函数而没有错误。现在我正在尝试从C#中调用它。
这是我的C#代码:
    public static class DllHelper
{

    [DllImport("rep.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int mymain(int iArgs, string aArgs);
}

class Program
{



    static void Main(string[] args)
    {
        string s = "my string data";
        DllHelper.mymain(0, s);
    }
}

当我运行它时,我得到了

System.Runtime.InteropServices.SEHException:“外部组件引发了异常。”

我已经没有更多的想法了。

TIA


1
std::wstring是C++的一个类...你不能期望一个C#字符串会自动转换成它。 - yms
阅读此处:https://social.msdn.microsoft.com/Forums/en-US/fec28110-7a53-4fb5-8db6-3463aee768e1/marshalling-a-string-by-reference-from-c-to-unmanaged-c-and-back?forum=clr - yms
我实现了你的建议,并保留了C#调用,但期望C++ dll中的参数为LPTSTR。我能够调用它,但是在dll中得到的数据是垃圾。 myArgsPtr = 0x000000f3cabfec80 L"倯瑡⁨㩣瑜浥屰獪⹲硴⁴䈯捡畫印捥牵瑩⁹獪⹲p" - Jeff
3个回答

2

请在您的C或C++函数中,指定Unicode并使用printf函数的"%S"(大写'S'表示宽字符字符串),或者使用std::wcout

如果不这样做,可能会打印出奇怪的结果或在找到第一个空字符时终止。此外,您可能需要传递字符串的长度,但这完全取决于您自己。

请注意,C++函数的签名将使用LPCWSTRconst wchar_t*)作为 myArgs 参数。

public static class DllHelper
{

    [DllImport("rep.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
    public static extern int mymain(int iArgs, string aArgs);
}

class Program
{
    static void Main(string[] args)
    {
        string s = "my string data";
        DllHelper.mymain(0, s);
    }
}

#ifdef __cplusplus
extern "C" {
#endif

int __declspec(dllexport) mymain(int i, const wchar_t* myArgs)
{
    #ifdef __cplusplus
    std::wcout<<std::wstring(myArgs)<<L"\n";
    #else
    printf(L"%S\n", myArgs);
    #endif
}

#ifdef __cplusplus
}
#endif

1
根据您的最后一条评论,您可能需要:
[DllImport("rep.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]

无论如何,由于我没有rep.dll文件,很难猜测。


1
您代码中使用的命名方式为:
mymain(int iArgs, string aArgs);
这让我想到你可能正在尝试传递一个字符串数组(类似于wmain(int argc, wchar_t** argv))。如果是这样,那么在本地DLL端,您的函数原型应该如下所示:
extern "C" int __declspec(dllexport) mymain(int iArgs, wchar_t** aArgs)

在C#端,您需要编写一个类似于以下的PInvoke声明:
[DllImport("rep.dll", 
    CallingConvention=CallingConvention.Cdecl, 
    CharSet=CharSet.Unicode)]
public static extern int mymain(int iArgs, [In] string[] aArgs);

你可以在C#中像这样调用它:
string[] test = { "C64", "Bravo", "Charlie" };
int returnCode = mymain(test.Length, test);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接