Frage

Mögliches Duplikat:
C ++ - Plugin für Unity "EntryPointNotFoundExeption"

Ich verstehe, wie man Namensänderungen mit externem "C" für einzelne Funktionen in C ++ verhindert, aber gibt es eine Möglichkeit, dies beim Exportieren von Mitgliedsfunktionen zu verhindern?

In: WMIWrapper.cpp

namespace WMIWrapper
{

    extern "C" {

        WMIWrapper::WMIWrapper()
        {
            _locator = NULL;
            _service = NULL;
            _monitors = NULL;
        }

        WMIWrapper::~WMIWrapper()
        {
            if(_service != NULL)
                _service->Release();
            if(_locator != NULL)
                _locator->Release();
        }

        void WMIWrapper::CreateCOM(wchar_t* err, int errLength)
        {
            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; 
            } 

            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;
            } 

            if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&_locator))))  
            {  
                ERRStream << "Unable to create a WbemLocator: " << std::hex << hRes << endl;   
            }

            if(ERRStream != NULL)
                wcscpy_s(err, errLength, ERRStream.str().c_str());
        }

        void WMIWrapper::CreateService(wchar_t* err, int errLength)
        {
            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; 
            }  

            if(ERRStream != NULL)
                wcscpy_s(err, errLength, ERRStream.str().c_str());
        }

        void WMIWrapper::GetMonitors(wchar_t* err, int errLength)
        {
            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)))
            {
                ssMonitorDescription << "Unable to retrieve desktop monitors: " << std::hex << hRes << endl;
                wcscpy_s(err, errLength, ssMonitorDescription.str().c_str());
                return;
            }

            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)
                {
                    ssMonitorDescription << "Description: " << vRet.bstrVal << endl;
                    VariantClear(&vRet);
                }
            }

            clsObj->Release();

            wcscpy_s(err, errLength, ssMonitorDescription.str().c_str());
        }

        void WMIWrapper::HelloWorld(wchar_t* testString, int length)
        {
            wstring hello = L"Hello World";
            wcscpy_s(testString, length, hello.c_str());
        }
    }
}

In: 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")  

namespace WMIWrapper
{
    extern "C" {

        class WMIWrapper 
        {  
        public:
            WMIWrapper();
            ~WMIWrapper();


            __declspec(dllexport) void CreateCOM(wchar_t*, int);
            __declspec(dllexport) void CreateService(wchar_t*, int);
            __declspec(dllexport) void GetMonitors(wchar_t*, int);
            __declspec(dllexport) void HelloWorld(wchar_t*, int);


        private:
            IWbemLocator* _locator;
            IWbemServices* _service;
            IEnumWbemClassObject* _monitors;
        };
    }
}

#endif

Wenn ich diese Funktionen jetzt in Unity verwenden möchte, muss ich die DLL dekompilieren, um herauszufinden, was meine Einstiegspunkte für die Funktionsnamen sind.Ich will das nicht tun müssen.

Ich weiß, dass ich mit dem externen "C" etwas übereifrig geworden bin...

War es hilfreich?

Lösung

UPDATE:Wie @peechykeen in den Kommentaren darauf hingewiesen hat, wenn Sie verwenden werden .def dann können Sie Ihre verstümmelten Namen direkt umbenennen.Ich lasse die ursprüngliche Antwort, obwohl es viel nützlicher ist, die exportierten Namen auszublenden, anstatt sie umzubenennen.

Ursprüngliche Antwort:

Eine Möglichkeit besteht darin, die exportierten Namen hinter Ordnungszahlen zu "verstecken".Dafür müssen Sie ein definieren.def-Datei und geben Sie dann in den Exportbereich alle exportierten Namen ein, die Sie ausblenden möchten.Um beispielsweise einer durch eine Boost-Serialisierung exportierten Funktion die Ordnungszahl 1 zuzuweisen, würden Sie dies tun:

EXPORTS
??0?$oserializer@Vportable_binary_oarchive@@U?$pair@$$CBHH@std@@@detail@archive@boost@@QEAA@XZ  @1  NONAME

Und so weiter für alle Funktionen.Dies manuell zu tun ist sowohl mühsam als auch fehleranfällig.Und Sie erhalten jedes Mal Linkfehler, wenn Sie einen Teil der exportierten Oberfläche ändern.Um es halbautomatisch zu machen, benutze ich Dependency Walker und ein Perl-Skript.Es funktioniert so:

  1. In .platzierungsmarkierungen für DEF-Dateien im Exportbereich:

    EXPORTS
    ;BEGIN_RENAMING_TAG
    ;END_RENAMING_TAG
    
  2. Laden Sie die Binärdatei in Dependency Walker, gehen Sie zum Fenster exportierte Funktionen, wählen Sie alle exportierten Funktionen aus und kopieren Sie sie in die Zwischenablage.

  3. Hinter dem kopierten Text zwischen BEGIN / END-Tags in der .def-Datei.
  4. Führen Sie das folgende Perl-Skript auf dem aus .def-Datei:

    #perl -w
    print $ARGC;
    die "ERROR: Provide name of one DEF file to process\n" if @ARGV != 1;
    
    my $renaming = 0;
    my $counter = 1;
    my $fileName = $ARGV[0];
    my @lines;
    open(FILE, $fileName) or die $!;
    while(<FILE>)
    {
        if(/;END_RENAMING_TAG/)
        {
            $renaming = 0;
        }
    
        if($renaming == 1)
        {
            chomp;
            my $line = $_."\t@".$counter."\tNONAME";
            push(@lines, $line);
            ++$counter;
        }
        else
        {
            chomp;
            push(@lines, $_);
        }
    
        if(/;BEGIN_RENAMING_TAG/)
        {
            $renaming = 1;
        }
    }
    
    close FILE;
    open(FILE, ">$fileName") or die $!;
    print FILE join("\n", @lines);
    close FILE;
    
  5. Einträge in Ihrem .def-Datei sind jetzt alle in <entry> @<ordinal> NONAME Formatierung.

Jetzt verwende ich diese Ordnungszahlen nicht, um auf die Funktionen zuzugreifen, sondern benenne sie einfach um, da es mich stört, Hunderte exportierter Funktionen verfügbar zu machen, die ich nicht benötige (Boost-Serialisierung, die ich wiederum verwende) dllexport verknüpfung seiner Funktionen zu erzwingen).Sie müssten also mehr im Perl-Skript tun und sagen, exportieren Sie eine Aufzählung mit Funktionsnamen und Ordnungszahlen.Wenn Sie dies richtig machen möchten, müssten Sie einen Entmischungsalgorithmus im Perl-Skript implementieren, der Ihnen genaue Namen gibt, auf Überladen achten (gleicher Name, unterschiedliche Argumente) und die Aufzählungsnamenkonstanten beibehalten.

Um auf die Funktionen hinter Ordnungszahlen zuzugreifen, verwenden Sie GetProcAddress aber wirf die Ordnungszahl in LPCSTR .Weitere Informationen finden Sie in der Dokumentation zur Funktion.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top