Avatar billede jakobdo Ekspert
02. juli 2004 - 10:35 Der er 29 kommentarer og
1 løsning

Load Dll dynamisk, og bruge den funktioner.

Måske giver jeg for let op, men jeg er ved at blive tosset over hvordan jeg skal bruge DLL'er effektivt...

Min kode til DLL'en er sådan her:

#include <windows.h>

HHOOK g_hMouseHook = NULL;
HWND hWndApp      = NULL;
HINSTANCE hInstDLL = NULL;

bool WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved)
{
    UNREFERENCED_PARAMETER(lpvReserved);
    switch(fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            MessageBox(NULL,"PAttach","SET",MB_OK);
            hInstDLL = hInstance;
            break; 

        case DLL_THREAD_ATTACH:
            MessageBox(NULL,"TAttach","SET",MB_OK);
            break;

        case DLL_THREAD_DETACH:
            MessageBox(NULL,"TDetach","SET",MB_OK);
            break;

        case DLL_PROCESS_DETACH:
            MessageBox(NULL,"PDetach","SET",MB_OK);
            break;
    }
    return true;
}

bool __declspec(dllexport)printfDll(LPTSTR lpTxt)
{
    MessageBox(NULL,lpTxt,"INFO",MB_OK);
    return true;
}

Og til selve programmet:

#include <stdio.h>
#include <windows.h>

typedef VOID (*MYPROC)(LPTSTR);

void error(LPSTR);

VOID main(VOID)
{
    MYPROC ProcAdd;
    HINSTANCE hinstLib;
    bool fRunTimeLinkSuccess = FALSE;

    // Get a handle to the DLL module.
    hinstLib = LoadLibrary("mydll.dll");

    // If the handle is valid, try to get the function address.
    if (hinstLib != NULL)
    {
        printf("+ LoadLibrary Done\n");
        ProcAdd = (MYPROC) GetProcAddress(hinstLib, "printDll");

        // If the function address is valid, call the function.
        if (NULL != ProcAdd)
        {
            printf("+ GetProcAddress Done\n");
            fRunTimeLinkSuccess = TRUE;
            (ProcAdd) ("message via DLL function\n");
        }
        else
        {
            printf("- GetProcAddress Failed\n");
            error("GetProcAddress");
        }

    // Free the DLL module.
    FreeLibrary(hinstLib);
    }
    else
    {
        printf("- LoadLibrary Failed\n");
        error("LoadLibrary");
    }

    // If unable to call the DLL function, use an alternative.
    if (! fRunTimeLinkSuccess)
        printf("message via alternative method\n");
}

void error(LPSTR lpszFunction)
{
    CHAR szBuf[80];
    DWORD dw = GetLastError();

    sprintf(szBuf, "%s failed: GetLastError returned %u\n", lpszFunction, dw);

    MessageBox(NULL, szBuf, "Error", MB_OK);
    ExitProcess(dw);
}

Jeg får fejlen: Hvor den skal GetProcAddress, og windows error code: 127 The specified procedure could not be found.

Men den skulle da gerne være der, eller tager jeg fejl?

Noge som kan hjælpe?
Avatar billede arne_v Ekspert
02. juli 2004 - 10:39 #1
bool __declspec(dllexport)printfDll(LPTSTR lpTxt)

ProcAdd = (MYPROC) GetProcAddress(hinstLib, "printDll");

med eller uden f ?
Avatar billede jakobdo Ekspert
02. juli 2004 - 10:43 #2
Har ændret: ProcAdd = (MYPROC) GetProcAddress(hinstLib, "printDll");
til:
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "printfDll");
Men får samme fejl!
Avatar billede arne_v Ekspert
02. juli 2004 - 10:48 #3
Der er også lidt blandede udmeldinger om returværdi bool eller void.

Men det tror jeg nu ikke har nogen effekt.
Avatar billede arne_v Ekspert
02. juli 2004 - 10:49 #4
Oversætter du som C eller C++ ?

Hvis C++ kan du prøve:

extern "C" {

}

omkring funktionen.
Avatar billede jakobdo Ekspert
02. juli 2004 - 10:53 #5
Jeg bruger BCC32, og mine filer ender på CPP, så det må være C++!

Jeg har nu sat dette på:
extern "C"
{
    bool __declspec(dllexport)printfDll(LPTSTR lpTxt)
    {
        MessageBox(NULL,lpTxt,"INFO",MB_OK);
        return true;
    }
}

Stadig ingenting...
Samme fejl...
Avatar billede jakobdo Ekspert
02. juli 2004 - 11:07 #6
Måske du kan hjælpe!

Det jeg ønsker er følgende:

En dll-fil, som indeholder 2 funktioner:

f.eks.:
int getValue();
void setValue(int i);
Avatar billede jakobdo Ekspert
02. juli 2004 - 11:40 #7
Nu er jeg kommet lidt længere:

test2dll.cpp
#include <windows.h>

static int i = 0;

extern "C"
int __declspec(dllexport) WINAPI GetInt()
{
    MessageBox (NULL, "GET", "INFORMATION", NULL );
    return i;
}

extern "C"
bool __declspec(dllexport) WINAPI SetInt(int t)
{
    MessageBox (NULL, "SET", "INFORMATION", NULL );
    i = t;
    return true;
}

test2exe.cpp
#include <stdio.h>
#include <windows.h>

typedef int (*MYPROC1)(void);
typedef bool (*MYPROC2)(int);

void error(LPSTR);

bool main(void)
{
    MYPROC1 ProcAdd1;
    MYPROC2 ProcAdd2;
    HINSTANCE hinstLib;
    bool fRunTimeLinkSuccess = false;

    // Get a handle to the DLL module.
    hinstLib = LoadLibrary("test2dll.dll");

    // If the handle is valid, try to get the function address.
    if (hinstLib != NULL)
    {
        printf("+ LoadLibrary Done\n");
        ProcAdd1 = (MYPROC1) GetProcAddress(hinstLib, "GetInt");
        ProcAdd2 = (MYPROC2) GetProcAddress(hinstLib, "SetInt");

        // If the function address is valid, call the function.
        if ((NULL != ProcAdd1) && (NULL != ProcAdd2))
        {
            printf("+ GetProcAddress Done\n");
            fRunTimeLinkSuccess = true;
            printf("Return Int: %d\n",ProcAdd1());
            ProcAdd2(2);
            printf("Return Int: %d\n",ProcAdd1());
            ProcAdd2(3);
            printf("Return Int: %d\n",ProcAdd1());
            MessageBox(NULL,"DONE",NULL,MB_OK);
        }
        else
        {
            printf("- GetProcAddress Failed\n");
            error("GetProcAddress");
        }

    // Free the DLL module.
    FreeLibrary(hinstLib);
    }
    else
    {
        printf("- LoadLibrary Failed\n");
        error("LoadLibrary");
    }

    // If unable to call the DLL function, use an alternative.
    if (!fRunTimeLinkSuccess)
        printf("message via alternative method\n");
    return false;
}

void error(LPSTR lpszFunction)
{
    CHAR szBuf[80];
    DWORD dw = GetLastError();

    sprintf(szBuf, "%s failed: GetLastError returned %u\n", lpszFunction, dw);

    MessageBox(NULL, szBuf, "Error", MB_OK);
    ExitProcess(dw);
}

Jeg får dog nogle mærkelige fejl, nå programmet har kørt...
Men det henter og sætter fint værdien...
Avatar billede jakobdo Ekspert
02. juli 2004 - 11:47 #8
Det kan muligvis være noget i min DLL, da fejlen ikke ser ud til at være i selve EXE, programmet.
Nogle ideer?
Avatar billede arne_v Ekspert
02. juli 2004 - 11:52 #9
Ikke lige umiddelbart.

Jeg kan selvfølgelig prøve at eksperimentere lidt i aften.
Avatar billede jakobdo Ekspert
02. juli 2004 - 11:55 #10
Det ville være super!
Lidt irreterende at det nu virker efter hensigten, men der kommer 3 fejl fra Windows op efter programmet er kørt...
Avatar billede jakobdo Ekspert
02. juli 2004 - 22:36 #11
Jeg har fundet ud af følgende:

Hvis jeg laver funktionen:

int getValue()

så virker det fint!

Laver jeg funktionen:
void setValue(int i)

Så crasher den!

Nogle ideer til om dette kan løses?

Værdien sættes jo som sådan fint nok, men den crasher når DLL'en skal releases!
Faktisk sker det efter den er releaset.
Avatar billede arne_v Ekspert
03. juli 2004 - 15:42 #12
Hm.

Jeg måtte ændre det til:

ProcAdd1 = (MYPROC1) GetProcAddress(hinstLib, "_GetInt@0");
ProcAdd2 = (MYPROC2) GetProcAddress(hinstLib, "_SetInt@4");

og så virkede det uden fejl.

Hvordan bygger du ?

Jeg bygger med:

cl /LD /Fetest2dll.dll test2dll.cpp user32.lib

cl test2exe.cpp user32.lib
Avatar billede jakobdo Ekspert
04. juli 2004 - 02:14 #13
Jeg bygger DLL'en med:

bcc32 -tWD testdll.cpp
og selve exe-filen:
bcc32 testexe.cpp

Men hvis du har en anden løsning, gider du smide koden her?

Jeg bruger jo dynamisk loading af DLL'en, og så skal jeg vel ikke bruge LIB?
Avatar billede arne_v Ekspert
04. juli 2004 - 10:55 #14
Ah med BCC så:
  - skulle jeg også kun bruge GetInt og SetInt
  - fik en fejl efter afslutning af programmet

Det kigger jeg lidt videre på.
Avatar billede arne_v Ekspert
04. juli 2004 - 10:56 #15
user32.lib er nødvendig for at MS VC++ kan finde MessageBox - det har intet med
din DLL at gøre
Avatar billede jakobdo Ekspert
04. juli 2004 - 10:58 #16
Ok, men du får altså også en fejl når programmet er kørt "færdigt"?
Avatar billede arne_v Ekspert
04. juli 2004 - 10:59 #17
Jep
Avatar billede arne_v Ekspert
04. juli 2004 - 11:08 #18
Prøv lige med:

typedef int WINAPI (*MYPROC1)(void);
typedef bool WINAPI (*MYPROC2)(int);
Avatar billede arne_v Ekspert
04. juli 2004 - 11:40 #19
Det fjerner fejlen hos mig !
Avatar billede jakobdo Ekspert
04. juli 2004 - 12:14 #20
Det fjerner også fejlen her!
Nogen ide til hvorfor?

Men anyway, du hjalp jo endnu engang, smider du et svar? :o)
Avatar billede arne_v Ekspert
04. juli 2004 - 12:57 #21
svar
Avatar billede arne_v Ekspert
04. juli 2004 - 12:58 #22
Du har erklæret dem som WINAPI i test2dll.cpp så skal de også
erklæres som WINAPI i test2exe.cpp ellers kan der ske grimme ting.
Avatar billede jakobdo Ekspert
04. juli 2004 - 13:06 #23
Ok, men hvis jeg fjerner WINAPI alle steder, så virker det slet ikke!
Har du tilfældigvis et link, hvor jeg kan læse hvad WINAPI gør?
Avatar billede arne_v Ekspert
04. juli 2004 - 14:06 #24
WINAPI styrer calling convention.

Uden WINAPI skal du bruge:

        ProcAdd1 = (MYPROC1) GetProcAddress(hinstLib, "_GetInt");
        ProcAdd2 = (MYPROC2) GetProcAddress(hinstLib, "_SetInt");
Avatar billede arne_v Ekspert
04. juli 2004 - 14:08 #25
Avatar billede jakobdo Ekspert
04. juli 2004 - 15:52 #26
Ok, men er der nogen "forskel" på at bruge WINAPI eller ProcAdd1 = (MYPROC1) GetProcAddress(hinstLib, "_GetInt");

Eller er forskellen ens?
Avatar billede arne_v Ekspert
04. juli 2004 - 15:58 #27
Ingen funktionel forskel.

Men det er to forskellige måder at lave et kald på.

Bare kalderen og den kaldte er enige om konventionen, så virker det.

Det er også lige godt at køre i venstre side af vejen som i højre side af vejen
bare man er enige i et land om hvad man gør.

:-)
Avatar billede jakobdo Ekspert
04. juli 2004 - 15:59 #28
Ok, men du har jo ret meget styr på C++ (har jeg efterhånden erfaret) hvilken konvention vil du bruge? Eller bruger du?
Avatar billede arne_v Ekspert
04. juli 2004 - 16:05 #29
Jeg programmerer faktisk ikke så meget C/C++ på Win32 platform.

I rene C/C++ apps angiver jeg ikke nogen konvention, hvilket defaulter
til __cdecl.

Hvis jeg skal lave DLL'er som skal kaldes fra VB bruger jeg WINAPI (alias for __stdcall).

Hvis jeg skal lave DLL'er som skal kaldes fra Java bruger jeg JNICALL (også
alias for __stdcall).
Avatar billede jakobdo Ekspert
04. juli 2004 - 16:07 #30
Ok, takker for info!
Og igen tak for hjælpen! :o)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester