C ++插件统一性QUOT; EntryPointNotFoundExeption" [英] C++ plugin for Unity "EntryPointNotFoundExeption"

查看:503
本文介绍了C ++插件统一性QUOT; EntryPointNotFoundExeption"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些严重的帮助这里...我想要么得到我的出口成员函数,这样我就可以叫他们在C#中

I need some serious help here... I'm trying to either get my member functions exported so I can call them in C#

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来执行这些功能,并返回结果,但返回相同的错误。

So I'm trying to call those member functions from the Unity script and I'm getting the EntryPointNotFoundExeption error. I thought maybe it was because you couldn't export member functions, so I tried writing that "Interface.cpp" to execute those functions and return the result but that returns the same error.

更新

每建议,我已经改变了我的C ++函数以这种格式

Per suggestion I have changed my C++ functions to this format

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

HOWEVER, I'm still getting "EntryPointNotFoundExeption" when calling the first function, CreateCOM();

推荐答案

这是窗口?因为你缺少你

Is this windows? Because you are missing your

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

定义如果是Windows。

definition if it is windows.

请参见编程Windows:第五版的第21章。由Charles Petzold的

See chapter 21 of "Programming Windows: Fifth Edition" by Charles Petzold.

如果你不用它。得到它。所有的Windows程序员应该看它。

If you don't have it. Get it. All windows programmers should read it.

图书馆第一次开始时,DllMain函数被调用时
将终止。到DllMain的第一个参数是该库的实例句柄
。如果库使用需要一个
实例句柄(如DialogBox的)资源,应该实例句柄保存为
全局变量。到的DllMain最后一个参数是由
系统保留...

The DllMain function is called when the library first begins and when it terminates. The first parameter to DllMain is the instance handle of the library. If your library uses resources that require an instance handle (such as DialogBox), you should save hInstance as a global variable. The last parameter to DllMain is reserved by the system...

DLL_PROCESS_ATTACH的fdwReason值表示
动态链接库一直映射到
进程的地址空间。这是为的lib的临时做任何初始化任务$ B $一个提示B检查要求的服务从处理后续请求....

A fdwReason value of DLL_PROCESS_ATTACH indicates that the dynamic-link library has been mapped into the address space of a process. This is a cue for the lib rary to do any initialization tasks it requires to service subsequent requests from the process....

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

If the initialization is successful, DllMain should return a nonzero value. Returning 0 will cause Windows to not run the program.

在fdwReason具有DLL_PROCESS_DETACH的值,这意味着
DLL不再需要由进程..清理...

When fdwReason has a value of DLL_PROCESS_DETACH, it means that the DLL is no longer needed by the process.. clean up...

Visual Studio中的较新版本,可能会为你做这一点 - 我不知道那一部分

Later versions of Visual Studio, may do this for you--I am not sure about that part.

另外,如果你的函数名正在错位,你会得到一个EntryPointNotFound例外。
你的函数名正在甚至与外部的C的宣言错位的原因是因为你已经放置的externC围绕类方法。为了使,要没有你所要做的C风格的函数声明的错位的名称使用。

Also, you will get an EntryPointNotFound exception if your function names are being mangled. The reason your function names are being mangled even with the extern "C" declaration is because you have placed extern "C" around class methods. In order for that to work without the mangled names you have to do C style function declarations.

#ifdef _cplusplus
extern "C" {
#endif

__declspec(dllexport) wstring CreateCOM();

...



一类的范畴之外。通过让那些声明为类成员,名字仍然会错位,甚至与外部的C声明。

outside the context of a class. By having those declared as class members, the names will still be mangled, even with the extern "C" declaration.

这篇关于C ++插件统一性QUOT; EntryPointNotFoundExeption&QUOT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆