Unity的“C ++插件”“EntryPointNotFoundExeption”

我需要一些严肃的帮助……我试图让我的成员函数导出,所以我可以在C#中调用它们

WMIWrapper.h

#ifndef _WMIWRAPPER_H_ #define _WMIWRAPPER_H_ #include  #include  #include  #include  using std::endl; using std::wstring; using std::wstringstream; #pragma comment(lib, "wbemuuid.lib") static class WMIWrapper { public: __declspec(dllexport) WMIWrapper(); __declspec(dllexport) ~WMIWrapper(); __declspec(dllexport) wstring CreateCOM(); __declspec(dllexport) wstring CreateService(); __declspec(dllexport) wstring GetMonitors(); private: IWbemLocator* _locator; IWbemServices* _service; IEnumWbemClassObject* _monitors; }; #endif 

WMIWrapper.cpp

 #include "WMIWrapper.h" extern "C" { WMIWrapper::WMIWrapper() { _locator = NULL; _service = NULL; } WMIWrapper::~WMIWrapper() { if(_service != NULL) _service->Release(); if(_locator != NULL) _locator->Release(); } wstring WMIWrapper::CreateCOM() { wstringstream ERRStream (wstringstream::in | wstringstream::out); HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(FAILED(hRes)) { ERRStream << "Unable to launch COM: 0x" << std::hex << hRes << endl; return L""; } hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0); if(FAILED(hRes)) { ERRStream << "Unable to set security level for COM: " << std::hex << hRes << endl; return L""; } if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&_locator)))) { ERRStream << "Unable to create a WbemLocator: " << std::hex << hRes <ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &_service))) { ERRStream << "Unable to connect to \"CIMV2\": " << std::hex << hRes <ExecQuery(L"WQL", L"SELECT * FROM Win32_DesktopMonitor", WBEM_FLAG_FORWARD_ONLY, NULL, &_monitors))) { //ERRStream << "Unable to retrieve desktop monitors: " << std::hex << hRes <Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE) { if(FAILED(hRes)) break; VARIANT vRet; VariantInit(&vRet); if(SUCCEEDED(clsObj->Get(L"Description", 0, &vRet, NULL, NULL)) && vRet.vt == VT_BSTR) { //std::wcout << L"Description: " << vRet.bstrVal << endl; ssMonitorDescription << "Description: " << vRet.bstrVal <Release(); return ssMonitorDescription.str(); } } 

Interface.cpp

 #include "WMIWrapper.h" extern "C" { __declspec( dllexport ) wstring GetMonitor() { WMIWrapper* wmiWrapper = new WMIWrapper(); wmiWrapper->CreateCOM(); wmiWrapper->CreateServiceW(); return wmiWrapper->GetMonitors(); } } 

Unity脚本

 using UnityEngine; using System.Runtime.InteropServices; using System; public class HardwareDiagnostics : MonoBehaviour { //[DllImport("WMIWrapper", EntryPoint="CreateCOM", CharSet = CharSet.Unicode)] //static extern String CreateCOM(); // //[DllImport("WMIWrapper", EntryPoint="CreateService", CharSet = CharSet.Unicode)] //static extern String CreateService(); // //[DllImport("WMIWrapper", EntryPoint="GetMonitors", CharSet = CharSet.Unicode)] //static extern String GetMonitors(); [DllImport("WMIWrapper", EntryPoint = "GetMonitor", CharSet = CharSet.Unicode)] static extern string GetMonitor(); // Use this for initialization void Start () { Debug.Log(GetMonitor()); Debug.Log ("Cock"); } // Update is called once per frame void Update () { } } 

所以我试图从Unity脚本调用这些成员函数,我得到了EntryPointNotFoundExeption错误。 我想也许是因为你无法导出成员函数,所以我尝试编写“Interface.cpp”来执行这些函数并返回结果但返回相同的错误。

UPDATE

根据建议我已将C ++函数更改为此格式

 void WMIWrapper::CreateCOM(wchar_t* err, int errLength) { .../Determine wstringstream ERRStream wcscpy_s(err, errLength, ERRStream.str().c_str()); } 

而我的C#就像这样:

 public class HardwareDiagnostics : MonoBehaviour { [DllImport( "WMIWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern void CreateCOM(StringBuilder str, int length); [DllImport( "WMIWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern void CreateService(StringBuilder str, int length); [DllImport( "WMIWrapper", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern void GetMonitors(StringBuilder str, int length); // Use this for initialization void Start () { StringBuilder buffer = new StringBuilder(255); CreateCOM(buffer, buffer.Capacity); Debug.Log(buffer.ToString()); CreateService(buffer, buffer.Capacity); Debug.Log(buffer.ToString()); GetMonitors(buffer, buffer.Capacity); Debug.Log(buffer.ToString()); } // Update is called once per frame void Update () { } } 

但是,在调用第一个函数CreateCOM()时,我仍然得到“EntryPointNotFoundExeption”;

这是窗户吗? 因为你错过了你的

 Bool WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID); 

定义是否是windows。

请参阅Charles Petzold撰​​写的“编程Windows:第五版”的第21章。

如果你没有它。 得到它。 所有Windows程序员都应该阅读它。

当库首次开始和终止时,将调用DllMain函数。 DllMain的第一个参数是库的实例句柄。 如果您的库使用需要实例句柄的资源(例如DialogBox),则应将hInstance保存为全局变量。 DllMain的最后一个参数由系统保留……

DLL_PROCESS_ATTACH的fdwReason值表示动态链接库已映射到进程的地址空间。 这是lib rary的一个提示,它可以执行任何初始化任务,以便为进程的后续请求提供服务….

如果初始化成功,则DllMain应返回非零值。 返回0将导致Windows无法运行该程序。

当fdwReason的值为DLL_PROCESS_DETACH时,表示进程不再需要DLL ..清理…

Visual Studio的更高版本可能会为您执行此操作 – 我不确定该部分。

此外,如果您的函数名被破坏,您将获得一个EntryPointNotFoundexception。 即使使用extern“C”声明,您的函数名称被破坏的原因是因为您在类方法周围放置了外部“C”。 为了使它在没有错位名称的情况下工作,您必须执行C样式函数声明。

 #ifdef _cplusplus extern "C" { #endif __declspec(dllexport) wstring CreateCOM(); ... 

在课堂上下文之外。 通过将那些声明为类成员,即使使用extern“C”声明,名称仍然会受到损坏。

这会有所帮助吗?

将std :: wstring的内容从C ++返回到C#

如何:使用C ++ Interop编组Unicode字符串

字符串的默认封送

错误来自于函数名称被C ++编译器破坏的事实。 我认为在.cpp中用extern“C”{}包装函数声明解决了这个问题,但我猜不是。

 [DllImport( "WMIWrapper", EntryPoint = "?CreateCOM@WMIWrapper@1@SAXPA_WH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern void CreateCOM(StringBuilder str, int length); [DllImport( "WMIWrapper", EntryPoint = "?CreateServiceW@WMIWrapper@1@SAXPA_WH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern void CreateService(StringBuilder str, int length); [DllImport( "WMIWrapper", EntryPoint = "?GetMonitors@WMIWrapper@1@SAXPA_WH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern void GetMonitors(StringBuilder str, int length); 

如果有人知道如何在这种情况下正确使用extern“C”,那将非常有帮助。