![](/img/trans.png)
[英]AccessViolationException when calling C++/CLI wrapper of Caffe
[英]AccessViolationException when calling C++/CLI wrapper from C#
我试图创建一个C ++ / CLI包装器,用于将类对象从非托管C ++ DLL传递到托管C#代码中(该代码随后在网页上显示对象的内容)。 我在非托管C ++代码中具有以下功能:
ProbeState _cdecl ManagerAPI::getProbeState()
{
ProbeState ps = psdao.getLastProbeStateByProbeId(1);
return ps;
}
我在C ++ / CLI包装器中调用该函数:
using namespace System;
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "../ManagerApp/ProbeState.h"
typedef ProbeState(*PSFunc)(void);
public ref class ManagerAPIWrapper
{
private:
HINSTANCE managerApp;
public:
ManagerAPIWrapper()
{
managerApp = LoadLibrary(L"ManagerApp.dll");
}
System::String^ testFunc()
{
PSFunc psFunc = (PSFunc)GetProcAddress(managerApp, "?getProbeState@ManagerAPI@@QAA?AVProbeState@@XZ");
ProbeState *ps = new ProbeState(psFunc());
System::String ^s = gcnew System::String(ps->getName().c_str());
delete ps;
return s;
}
};
最后,我从C#控制器调用包装器:
ManagerAPIWrapper.ManagerAPIWrapper wrapper = new ManagerAPIWrapper.ManagerAPIWrapper();
ViewBag.DllMessage = wrapper.testFunc();
它总是在ProbeState行上抛出异常* ps = new ProbeState(psFunc());
不过,奇怪的是,当我将C ++ / CLI包装器作为具有主要功能的控制台应用程序进行编译时:
int _tmain(int argc, _TCHAR* argv[])
{
ManagerAPIWrapper::ManagerAPIWrapper wrapper;
System::Console::WriteLine(wrapper.testFunc());
getchar();
return 0;
}
此代码可以正常工作,并打印出C ++ DLL从数据库检索到的状态的名称。 从C#调用时,C ++ / CLI如何在控制台应用程序中工作并引发异常?
PS:包装程序使用/ clr选项进行编译。 当我使用/ clr:pure编译包装器时,异常与C#调用相同。 这是否意味着当包装器在C#应用程序中编译并从中调用时,它采用了纯选项?
包装器旨在在C ++和C#之间转换数据,因此,根据我的观点,不应在C#应用程序中使用更严格的选项对其进行编译。 有什么办法告诉C#编译器该程序集包含混合代码?
好的,我终于解决了这个问题。 经过数小时的尝试与失败方法来查找解决方案之后,我尝试首先直接从C#代码中从非托管DLL调用函数,然后再调用包装器的构造函数,并成功调用LoadLibrary。 现在,C#控制器中的代码如下所示:
[DllImport("C:\\ManagerApp.dll", CharSet = CharSet.Unicode,
EntryPoint = "?initFunc@ManagerAPI@@QAEHXZ")]
private static extern int initFunc();
public ActionResult APITest()
{
ViewBag.Message = "API output test page.";
if (initFunc() == 0)
{
ViewBag.Error = "Could not initialize the library.";
return View();
}
ManagerAPIWrapper.ManagerAPIWrapper wrapper = new ManagerAPIWrapper.ManagerAPIWrapper();
ViewBag.DllMessage = wrapper.testFunc();
return View();
}
我认为这可能有助于向非托管DLL的包装DLL添加依赖项,从而摆脱调用initFunc
的必要性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.