gpt4 book ai didi

c# - 从 C# Windows 应用程序调用 C dll 导致 svchost.exe 崩溃

转载 作者:行者123 更新时间:2023-11-30 01:39:32 28 4
gpt4 key购买 nike

我创建了一个 C DLL,以便我可以在我的 C# 应用程序中使用它。
我在 C++ 测试应用程序上测试了 DLL,它运行良好,但在 C# 应用程序中无法运行。
出于某种原因,我无法构建 DLL 的调试版本,因此我也无法在 Debug模式下运行 C# 应用程序。
DLL 调试配置不会找到 include 目录,而在 Release模式下,它工作得很好!
我需要说的是,我在下面给出了一个导致崩溃的特定方法,从 DLL 调用其他方法没有问题并且按预期工作。这是主要实现:
header 定义:

//use this function to classify an image
CDLL_API const char* Classify(const char* img_path, int N = 2);

.cpp 实现

CDLL_API const char* Classify(const char * img_path, int N)
{
auto classifier = reinterpret_cast<Classifier*>(GetHandle());
std::vector<PredictionResults> result = classifier->Classify(std::string(img_path), N);
std::string str_info = "";
std::stringstream ss;
for (size_t i = 0; i <result.size(); ++i)
{
auto label = result[i].label;
auto acc = result[i].accuracy;
ss << "label=" << label << ",acc=" << acc << "|";
}
return ss.str().c_str();
}

C# 代码:

[DllImport(@"CDll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern string Classify([MarshalAs(UnmanagedType.LPStr)]string img_path,int N = 2);

//...
var s = Classify(txtFilePath.Text, 2);
MessageBox.Show(s);

所以我完全没有想到真正的原因是什么。

最佳答案

我看到您在 C# PInvoke 声明中将调用约定指定为 Cdecl (CallingConvention = CallingConvention.Cdecl);因为这也是 C++ 代码中的默认调用约定,所以在这种情况下你不应该有任何调用约定不匹配。不过,请注意 C 接口(interface) DLL 的通用调用约定是 __stdcall .

我看到的问题是您从 C 接口(interface) API 返回字符串的方式

CDLL_API const char* Classify(const char * img_path, int N)
{
...
return ss.str().c_str();
}

(顺便说一句,我假设 ss 类似于 std::ostringstream 对象。)

您使用输出字符串流(调用其 str 方法)构建一个字符串,然后调用 c_str 获得原始 C 风格字符串指针。但是当函数退出时,字符串对象被销毁,所以 C 风格的原始字符串指针不再有效。

要将字符串从 C 接口(interface) DLL API 返回到 C#,您可以考虑以下选项之一:

  1. 从 C 接口(interface) DLL 返回一个 BSTR 字符串。使用 SysAllocString从原始 C 风格字符串指针创建 BSTR 对象。请注意,BSTR“自然地”存储 Unicode UTF-16 编码的字符串,因此请确保将您的字符串转换为此编码。 CLR 能够很好地管理 BSTR 字符串,因此您不必注意释放字符串内存:这将是 CLR 的工作。

  2. 向 C 接口(interface) DLL 函数添加几个参数:指向缓冲区的指针缓冲区大小。这将是一个输出字符串缓冲区,由调用者(例如 C#)分配,并且从 DLL 导出的 C 接口(interface) API 会将结果字符串写入该调用者提供的缓冲区。这就是例如GetWindowText Win32 API 可以(在 C# 端,输出字符串缓冲区可以由 StringBuilder 对象表示)。

关于c# - 从 C# Windows 应用程序调用 C dll 导致 svchost.exe 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45503410/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com