Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2009
    Messaggi
    487

    [C++] Problema simile al precedente

    ho un exe che utilizza una dll:

    //metodo, sempre static, che utilizza la dll (Client.cpp)
    codice:
    int Client::CallDllFunc(comando cmd)
        {
        HMODULE hmodule=::LoadLibrary("dll12.dll"); 
    
    	if(hmodule)
    		{
    		Command_Dll foo = (Command_Dll) GetProcAddress(hmodule,"foo"); 
    		foo(cmd);
    		FreeLibrary(hmodule);
    		}
    	return 0;
    	}
    e comando è così dichiarato nel file Client.h:

    codice:
    struct comando
    	{
    	string cmd;
    	string p1;
    	string p2;
    	string pNum;
    	string pAgg;
    	};

    Invece questa è la dll

    codice:
    #include <Windows.h>
    #include <string>
    
    using namespace std;
    
    //forse devo scrivere _declspec(dllexport)?? o mettere le parentesi graffe dopo extern "C" ossia
    /*
    extern "C" {
            struct comando{
    	string cmd;
    	string p1;
    	string p2;
    	string pNum;
    	string pAgg;
    	};
    }
    */
    extern "C" struct comando{
    	string cmd;
    	string p1;
    	string p2;
    	string pNum;
    	string pAgg;
    	};
    
    extern "C" _declspec(dllexport) void foo(comando cmd)
    {
    
    Sleep(200); //breakpoint i valori di cmd si trovano qui http://img638.imageshack.us/i/debug1.jpg/
    
    //blabla
    }
    da notare che la struttura cmd che avevo passato era così composta:

    cmd.cmd = "Prova"
    cmd.p1 = ":("
    cmd.p2 = ""
    cmd.pNum = ""
    cmd.pAgg = "Provaa"


    cosa può essere successo???? adesso mi sto rompendo di queste stringhe..e tra poco riscrivo la struttura di string in una bella stringa char * con dentro tutto quanto...ma mi rompe anche fare questo e che mi compaiano errori simili! -.-"

    //nota uso "multy byte characters set" ossia no UNICODE

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381

    Re: [C++] Problema simile al precedente

    Originariamente inviato da kirakira93
    cosa può essere successo????
    E' successo che hai rotto la compatibilità binaria tra sorgente e DLL.
    Il passaggio e restituizione di dati da un DLL deve avvenire sempre con tipi base.
    Leggi qui:
    http://chadaustin.me/cppinterface.html
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2009
    Messaggi
    487

    ahia

    brutta storia...ho letto la maggior parte della pagina..e questo:

    codice:
    Summary
    
    That's about it. In closure, I'll enumerate guidelines to keep in mind when creating C++ interface. You can look back on this as a reference or use it to help solidify your knowledge.
    
        * All interface classes should be completely abstract. Every method should be pure virtual. (Or inline... you could safely write inline convenience methods that call other methods.)
        * All global functions should be extern "C" to prevent incompatible name mangling. Also, exported functions and methods should use the __stdcall calling convention, as DLL functions and COM traditionally use that calling convention. This way, if a user of the library is compiling with __cdecl by default, the calls into the DLL will still use the correct convention.
        * Don't use the standard C++ library.
        * Don't use exception handling.
        * Don't use virtual destructors. Instead, create a destroy() method and an overloaded operator delete that calls destroy().
        * Don't allocate memory on one side of the DLL boundary and free it on the other. Different DLLs and executables can be built with different heaps, and using different heaps to allocate and free chunks of memory is a sure recipe for a crash. For example, don't inline your memory allocation functions so that they could be built differently in the executable and DLL.
        * Don't use overloaded methods in your interface. Different compilers order them within the vtable differently.
    mi piace poco..

    allora ho capito che dovrei evitare di usare std::string ma devo usare char *

    ma allora...se faccio una cosa del genere va bene?

    //sto usando le stringhe, ma non le uso come passaggio di parametri

    codice:
    extern "C" struct comando{
    	char * cmd;
    	char * p1;
    	char * p2;
    	char * pNum;
    	char * pAgg;
    	};
    
    extern "C" _declspec(dllexport) void foo(comando cmd)
    {
    std::string convert = cmd.cmd;
    //etc
    Sleep(200); 
    //blabla
    }
    In linea teorica direi che funziona, perché non interessa lo scambio di informazioni tra l'exe e la dll...inoltre ricordo che tempo fa...ahem..per fare una prova di dll iniection (sul mio pc), iniettai una dll che conteneva di tutto, nel senso di classi ed eredietarietà, funzioni static, funzioni virtual, eccezzioni e ovviamente std::string, vector, stringstream etcetcetc... e funzionava!
    quindi penso che non devo usare elementi C++ solo quando passo da exe a dll o da dll a dll...ma all'interno della dll, posso fare quello che "voglio"

    Mah, che ne pensi?

  4. #4
    Utente di HTML.it
    Registrato dal
    Sep 2009
    Messaggi
    487

    allora

    allora..questa è la mia nuova dll

    codice:
    #include <Windows.h>
    #include <string>
    
    using namespace std;
    
    extern "C" struct comando_dll
    	{
    	char * cmd;
    	char * p1;
    	char * p2;
    	char * pNum;
    	char * pAgg;
    	};
    
    extern "C" struct comando
    	{
    	string cmd;
    	string p1;
    	string p2;
    	string pNum;
    	string pAgg;
    	};
    
    extern "C" _declspec(dllexport) void foo(comando_dll cmd_dll)
    {
    comando cmd;
    
    cmd.cmd = cmd_dll.cmd;
    cmd.p1 = cmd_dll.p1;
    cmd.p2 = cmd_dll.p2;
    cmd.pNum = cmd_dll.pNum;
    cmd.pAgg = cmd_dll.pAgg;
    
    //....
    }
    e questa è la mia nuova funzione che chiama la dll

    codice:
        HMODULE hmodule=::LoadLibrary("dll12.dll"); 
    
    	if(hmodule)
    		{
    		comando_dll cmd_dll;
    		cmd_dll.cmd = new char [cmd.cmd.size() + 1];
    		cmd_dll.p1 = new char [cmd.p1.size() + 1];
    		cmd_dll.p2 = new char [cmd.p2.size() + 1];
    		cmd_dll.pNum = new char [cmd.pNum.size() + 1];
    		cmd_dll.pAgg = new char [cmd.pAgg.size() + 1];
    
    		strcpy(cmd_dll.cmd,cmd.cmd.c_str());
    		strcpy(cmd_dll.p1,cmd.p1.c_str());
    		strcpy(cmd_dll.p2,cmd.p2.c_str());
    		strcpy(cmd_dll.pNum,cmd.pNum.c_str());
    		strcpy(cmd_dll.pAgg,cmd.pAgg.c_str());
    
    		Command_Dll foo = (Command_Dll) GetProcAddress(hmodule,"foo"); 
    		foo(cmd_dll);
    		FreeLibrary(hmodule);
    
    		delete [] cmd_dll.cmd;
    		delete [] cmd_dll.p1;
    		delete [] cmd_dll.p2;
    		delete [] cmd_dll.pNum;
    		delete [] cmd_dll.pAgg;
    		}
    
    	return 0;
    	}

    adesso il codice funziona..ma ho notato ciò: provando ad iniettare il codice che utilizza la dll (ossia rendendolo una dll) ho visto che non è del tutto sbagliato ciò che dice http://chadaustin.me/cppinterface.html, infatti le prestazioni sono ridotte, e, se io uso le reference (vedi l'altra discussione) le prestazioni sono ridotte in maniera vereamente considerevole.

    Pertanto adesso che lo so, cercherò di usare il meno possibile elementi di c++ (mi limiterò a string e vector) nelle dll e di non usarli proprio al passaggio dei parametri.

    grazie di tutto, e sorgeranno porblemi vi terrò aggiornati

  5. #5
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    all'interno della dll, posso fare quello che "voglio
    Si. Il problema riguarda solo il passaggio di parametri.
    Entrando nel dettaglio, il fatto che ti funzioni "ora" non significa che funzioni "sempre".
    L'implementazione di una std::basic_string<> (ci cui una string è solo un typedef) varia da debug mode a release mode e non solo per il codice del debug appunto, ma anche per gli allocatori usati. Non c'è nessuna garanzia che la malloc o operator new o altro allocatore siano gli stessi tra il codice sorgente e la DLL, quindi non puoi fare nessuna assunzione che qualcosa allocato da una parte sia deallocabile dall'altra.
    E' comunque sufficiente provvedere a fornire due funzioni per risolvere il problema.
    codice:
    void* DLLAlloc(unsigned int);
    void DLLFree(void*);
    Il principio è semplice: se allochi con DLLAlloc() liberi la memoria con DLLFree().
    Per quanto riguarda la tua struttura la cosa si ripete. Però devi decidere dove e come allocare i campi. Se l'allocazione avviene lato sorgente, sei a posto; se avviene lato DLL sei a posto; se mischi le cose, sei del gatto.
    E comunque la struttura è meglio passarla come puntatore.
    codice:
    extern "C" struct comando{
    	char * cmd;
    	char * p1;
    	char * p2;
    	char * pNum;
    	char * pAgg;
    	};
    
    extern "C" _declspec(dllexport) void foo(comando* cmd)
    {
    std::string convert = cmd->cmd;
    //etc
    Sleep(200); 
    //blabla
    }
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381

    Re: allora

    Originariamente inviato da kirakira93
    infatti le prestazioni sono ridotte, e, se io uso le reference (vedi l'altra discussione) le prestazioni sono ridotte in maniera vereamente considerevole.
    Quoteresti la parte dove afferma questo? Perché io non la trovo.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.