2012-07-23 56 views
0

我在這裏需要一些嚴重的幫助......我想要麼得到我的出口成員函數,這樣我就可以叫他們在C#C++插件團結「EntryPointNotFoundExeption」

WMIWrapper.h

#ifndef _WMIWRAPPER_H_ 
#define _WMIWRAPPER_H_ 

#include <Windows.h> 
#include <sstream> 
#include <iostream> 
#include <WbemCli.h> 

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 << endl; 
      return L""; 
     } 

     const std::wstring& myWString = ERRStream.str(); 
     const LPCWSTR p = myWString.c_str(); 
     return p; 

    } 

    wstring WMIWrapper::CreateService() 
    { 
     wstringstream ERRStream (wstringstream::in | wstringstream::out); 
     HRESULT hRes; 
     if(_locator == NULL || FAILED(hRes = _locator->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 << endl; 
      return L""; 
     } 

     const std::wstring& myWString = ERRStream.str(); 
     const LPCWSTR p = myWString.c_str(); 
     return p; 
    } 

    wstring WMIWrapper::GetMonitors() 
    { 
     HRESULT hRes; 
     wstringstream ssMonitorDescription; 
     if(_locator == NULL 
      || _service == NULL 
      || FAILED(hRes = _service->ExecQuery(L"WQL", L"SELECT * FROM Win32_DesktopMonitor", WBEM_FLAG_FORWARD_ONLY, NULL, &_monitors))) 
     { 
      //ERRStream << "Unable to retrieve desktop monitors: " << std::hex << hRes << endl; 
      return L""; 
     } 

     IWbemClassObject* clsObj = NULL; 
     int numElems; 
     while((hRes = _monitors->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 << endl; 
       VariantClear(&vRet); 
      } 
     } 

     clsObj->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(); 
    } 
} 

團結腳本

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() { 

    } 


} 

不過,我仍然得到「 EntryPointNotFoundExeption「,當調用第一個函數,CreateCOM();

回答

2

這是窗口?因爲你想念你

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

定義它是否爲windows。

請參閱Charles Petzold編寫的「Programming Windows:Fifth Edition」的第21章。

如果你沒有它。得到它。所有的Windows程序員都應該閱讀它。

DllMain函數在庫首次啓動時以及 結束時調用。 DllMain的第一個參數是庫的實例句柄 。如果您的庫使用需要實例句柄(如DialogBox)的資源,則應將hInstance保存爲 全局變量。 DllMain的最後一個參數由 系統保留...

DLL_PROCESS_ATTACH的fdwReason值指示 動態鏈接庫已映射到 進程的地址空間。這是LIB郭寶宏做任何初始化任務 它需要從流程服務後續請求的提示....

如果初始化成功,應該的DllMain返回一個非零 值。返回0將導致Windows不運行該程序。

當fdwReason具有DLL_PROCESS_DETACH的值,這意味着 DLL由過程不再需要..清理...

的Visual Studio的後續版本,可以針對你 - 這樣做 - 我不確定那部分。

另外,如果函數名稱被損壞,您將得到EntryPointNotFound異常。 即使使用extern「C」聲明,你的函數名稱被破壞的原因是因爲你已經在類方法周圍放置了extern「C」。爲了使這個工作沒有這些損壞的名字,你必須做C風格的函數聲明。

#ifdef _cplusplus 
extern "C" { 
#endif 

__declspec(dllexport) wstring CreateCOM(); 

... 

一類的上下文之外。通過將這些聲明爲類成員,即使使用extern「C」聲明,名稱仍然會被破壞。

+0

哇,是用來代替int main(){}? 我在VS2010 Pro中創建了.dll,它的目的是通過Unity在windows中運行。 – 2012-07-24 14:30:20

+0

這是dll的主要() – 2012-07-24 14:32:32

+0

@JoshElias我正在尋找一個很好的鏈接,因爲我從Petzold的書中得到了這個。 – 2012-07-24 14:33:17

1
+0

你可能會發布一些代碼? – 2012-07-23 20:50:54

+0

在第一個問題中可以看到一個示例代碼... – Aybe 2012-07-23 20:58:39

+0

那麼您是使用UnmanagedFunctionPointerAttribute而不是DLLImport?我必須使用C++回調嗎?我的代碼究竟有哪部分是錯的?對不起,我只是發現你的回答非常神祕而模糊。我不是這方面的專家,我只是想寫我的第一個Unity插件。 – 2012-07-23 21:11:04

-1

錯誤來自於函數名被C++編譯器弄壞的事實。我以爲用extern「C」{}封裝了.cpp中的函數聲明就解決了這個問題,但我猜不是。

[DllImport("WMIWrapper", EntryPoint = "[email protected]@[email protected][email protected]", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 
private static extern void CreateCOM(StringBuilder str, int length); 

[DllImport("WMIWrapper", EntryPoint = "[email protected]@[email protected][email protected]", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 
private static extern void CreateService(StringBuilder str, int length); 

[DllImport("WMIWrapper", EntryPoint = "[email protected]@[email protected][email protected]", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 
private static extern void GetMonitors(StringBuilder str, int length); 

如果有人知道如何正確地使用外部的「C」在這種情況下,將是非常有益的。

+0

嗯,我實際上有這個錯誤一百萬次。不知道爲什麼我沒有想到它。 它可能說: EntryPointNotFoundExeption,沒有名爲GetMonitors的入口點... 無論如何,很高興你找到它。 – 2012-07-24 19:04:29

+0

w.r.t錯亂的名字,請參閱我即將提出的更新。 – 2012-07-24 19:08:14