[ borquee @ 21.05.2003. 19:13 ] @
Pokusavam da pozovem funkciju iz dll-a ali mi stalno prijavljuje da ima previse parametara.

pozivam dll sa LoadLibrary, i funkciju nalazim sa GetProcAddress...

funkcija ima dva parametra enum i unsigned int

greska je
error C2197: 'int (__stdcall *)(void)' : too many actual parameters
[ Ivan Dimkovic @ 21.05.2003. 22:49 ] @
Citat:

error C2197: 'int (__stdcall *)(void)' : too many actual parameters


Ocigledno je nisi implicitno deklarisao kao (enum, unsigned int) vec samo kao (void)

Code:

typedef HANDLE (*MOJAPROCEDURA)(enum, unsigned int);

MOJAPROCEDURA proc1;

todo: loadlibrary() i ostalo...

proc1 = (MOJAPROCEDURA)GetProcAddress( ... )

i pozivas kao:

(proc1)( parametri )...


[ borquee @ 21.05.2003. 23:28 ] @
Hvala,
Pomoglo je...

ovo je exportovana funkcija iz dll-a... a sta raditi kad je u pitanju ovako nesto

class neka_klasa* funkcija(enum A,unsigned long B)

ima li smisla umesto klase poturiti npr. char pointer, pa posle malo provaljivati sta se desava? (jeste malo reversing... izvinjavam se moderatoru)
[ Ivan Dimkovic @ 21.05.2003. 23:54 ] @
E tu ti vec ne mogu pomoci, to vec zahteva 1337 sKilZ
[ Jovan Marjanovic @ 22.05.2003. 10:03 ] @
Evo necega sto moze da pomogne (uzeto iz koda koji sam pisao pre par godina):


Code:


// svi include fajlovi ...
#include <nesto.h>
#include <svasta.h>

//struktura koja ce drzati sve pointere na funkcije
//(volim da pisem ovakve stvari

struct FUNC_TABLE_T
{
    char *name;
    void *func;
}lib_table[] = {
    {"nitialize_something",NULL},
    {"end_something",NULL},
    {"assign_something", NULL},
    {"remove_something",NULL},
    {"get_something", NULL},
    {NULL,NULL}
};

//globalna promenljiva koja ce imati pointer na otvoreni dll

HMODULE hndl_api = NULL;

int main (int argc, char **argv)
{

//definicije i prototipi
//naime, ovde pravis definises kako ce izgledati prototip funkcije koju ces da
//loadas iz dll-a sa tacnim parametrima koje ce funkcija da primi, i sa tipom
//promenljive koju ce funkcija da ti vrati

    typedef int (*FPROT1) (char*, char*);
    typedef int (*FPROT2) (void, unsigned long);
    typedef int (*FPROT3) (char*);
    typedef char* (*FPROT4) ();

//placeholderi za pointer na funkciju:

    FPROT1 initialize_something;
    FPROT2 end_something;
    FPROT3 assign_something;
    FPROT3 remove_something;
    FPROT4 get_something;

//ovde pokusavas da otvoris handle na dll, ako nema dll-a ode sve u pm.
//naravno, dll treba da bude ili u windows system direktoriju, ili u diru odakle
//radi tvoj softver

    hndl_api = LoadLibrary(_T("neki.dll"));
    if(hndl_api == NULL)
    {
        printf("dll ne postoji. bla bla bla\n");
        return 0;
    }

//ovde mapiras void pointere funkcija iz dll-a u strukturu koja je definisana
//ranije 
    lib_table[0].func = (void *) GetProcAddress (hndl_api, lib_table[0].name); 
    lib_table[1].func = (void *) GetProcAddress (hndl_api, lib_table[1].name); 
    lib_table[2].func = (void *) GetProcAddress (hndl_api, lib_table[2].name); 
    lib_table[3].func = (void *) GetProcAddress (hndl_api, lib_table[3].name); 
    lib_table[4].func = (void *) GetProcAddress (hndl_api, lib_table[4].name);

    if(lib_table[0].func == NULL ||
       lib_table[1].func == NULL ||
       lib_table[2].func == NULL ||
       lib_table[3].func == NULL ||
       lib_table[4].func == NULL)
    {
         printf("funkcije pogresno izmapirane, ili ne postoje...\n");
          return 0;
    }

//za coup de grace: casting void pointera na funkcije prema prototipu koji
//je definisan

    initialize_something = (FPROT1) lib_table[0].func;
    end_something = (FPROT2) lib_table[1].func;
    assign_something = (FPROT3) lib_table[2].func;
    remove_something = (FPROT3) lib_table[3].func;
    get_something = (FPROT4) lib_table[4].func;
    
//sada mozes da koristis te funkcije koje si izmapirao iz dll-a:

    if ((*initialize_something) (argv[1], argv[2]) <0)
    {
        printf("nesto nije u redu ...\n");
        return 0;
    }

//ovde ide puno koda koji radi nesto sa svim tim funkcijama

//oslobodi pointer na library
    FreeLibrary(hndl_api);

//kraj
    return 0;
}





Ovaj primer je naravno crippleware koda koji se nalazi u nasem produktu, jer ipak nesmem da kazem sve, ali mislim da potpuno objasnjava kako se mapiraju funkcije iz dll-a i kako se prave prototipi i kako se pravilno casta iz void pointera koji se dobije u pointer na definisani prototip.
Ista procedura moze da radi na drugim OS-ovima, jedina razlika je koje funkcije ce se koristiti za otvaranje biblioteke sa funkcijama i za mapiranje.

(iz dis 1337 sKilZ or wot? :P)
[ Ivan Dimkovic @ 22.05.2003. 10:30 ] @
Citat:

(iz dis 1337 sKilZ or wot? :P)


Mislim da je decko hteo da mapira neke funkcije koje vracaju klasu, i imaju tzv. "C++ mangled" names, a to su za mene vec 1337 sKilZ :)

[ Reljam @ 22.05.2003. 10:50 ] @
Ako ti je dll COM objekat, onda naravno mozes da koristis i #import da ga importujes, ili da izvuces tlb. Time dobijas i klase, koje naravno moraju da budu COMovske (ne mozes svaku C++ klasu da pretvoris u COM ali zato mozes obrnuto).
[ borquee @ 22.05.2003. 10:58 ] @
mangled names nisu problem, iz dependency viewer-a (v2.1) se vide parametri... problem je samo sto on vrati nepoznatog klasu...

klasa bi trebala da resi posao. ono sto klasa vrati je 8 bajtova (koji lice na dva int-a) i nesto teksta, iza texta sledi neki junk koji se ponavlja...

B.
[ borquee @ 22.05.2003. 11:02 ] @
cini mi se da nije...
kako prepoznati da li je dll COM objekat?
[ Jovan Marjanovic @ 22.05.2003. 11:05 ] @
Citat:
Ivan Dimkovic:
Citat:

(iz dis 1337 sKilZ or wot? :P)


Mislim da je decko hteo da mapira neke funkcije koje vracaju klasu, i imaju tzv. "C++ mangled" names, a to su za mene vec 1337 sKilZ :)



Da je hteo da mapira funkcije koje vracaju klasu u imaju mangled names, linker bi prijavio nesto drugacije. A da se to izbegne, funkcija koja vraca klasu u dll-u treba da bude deklarisana ovako:

Code:

#DllExports.h koji sam napisao pre par meseci bas za takav slucaj
#ifndef DLLEXPORTS_H
#define DLLEXPORTS_H

#ifdef __dll__
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif     // __dll__

#include "ObjStorage.h"
#include "ObjStorageInterface.h"

extern "C"
{
    IMPEXP ITestObject* CreateTestObjectClassInstance();
}
#endif    // DLLEXPORTS_H


Funkcija CreateTestObjectCLassInstance() vraca pointer na klasu, a mapira se u C++ kodu isto kao u prethodnom primeru.
Kako izmapirati klasu:
Code:

        //here write the object stream !!!!
        try
        {
            typedef ITestObject* (*FPROT1) ();
            HINSTANCE hndl = NULL;
            FPROT1 Ser;
            ITestObject* pTestObject = NULL;

            hndl = LoadLibrary("ObjStorage.dll");
            Ser = (FPROT1) (GetProcAddress(hndl, "CreateTestObjectClassInstance"));

            pTestObject =  /*static_cast<ITestObject*>*/ (Ser());

            (*pTestObject).Serialize(tmp);
            
            FreeLibrary (hndl);
        }
        catch(...)
        {
            cout << "Attempt at loading object and serialization failed!\n";
            cout.flush();
            return 0;
        }


A ako se pitate sta je ITestObject u mom kodu, evo ga:

Code:

class __declspec(dllexport) ITestObject
{
public:
    virtual void Serialize(char*) = 0;
    virtual void DeSerialize(char*) = 0;
};

Naime, napravljena je interface klasa...
Ali da ne duzim pricu, mangled C++ names treba izbegavati, i pravilno pisati DLL-ove, sa pravilno eksportovanim funkcijama.