我正在尝试创建一个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 ++ / CLI在控制台应用程序中工作,并在从C#调用时抛出异常?
P.S。:使用/ clr选项编译包装器。当我使用/ clr:pure编译包装器时,异常与C#调用相同。是否意味着当包装器在C#app中编译并调用时,它需要纯选项吗?
包装器用于在C ++和C#之间转换数据,因此根据我的意见,它不应该在C#app中使用更严格的选项进行编译。有没有办法告诉C#编译器这个程序集包含混合代码?
答案 0 :(得分:0)
[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
。