Funktionen aus einer dll mit C++ aufrufen?



  • Hallo Zusammen,

    ich habe mit C++ kaum Erfahrung und möchte gerne eine dll die ich mit C++ geschrieben habe ansprechen (Funktionen in der dll aufrufen).

    Ich habe es schon mit Hilfe eines Bsp. geschafft eine Funktion in der dll aufzurufen, leider war das Beispiel fast garnicht kommentiert so das ich mit vielen Fragezeichen im Kopf versucht habe eine weitere Funktion bei der eine Struktur übergeben wird aufzurufen. Ist leider bis jetzt fehlgeschlagen.

    Meine Bitte an euch, wie wird die Funktion CAN_Write, die sich in der a.dll befindet, von einem C++ Programm aufgerufen. Wenn es möglich ist dann bitte ich euch um ein bisschen Kommentar so das ich in Zukunft dieses Problem alleine Lösen kann.

    Als Entwicklungsumgebung benutze ich eVC++, da das Programm auf ein Windows CE Rechner läuft.

    Hier ist ein Programmauschnitt der a.dll mit der Funktion CAN_Write.

    struct CAN_MESSAGE
    {
    
    	unsigned char	Byte0;
    	unsigned char	Byte1;
    	unsigned char	Byte2;
    	unsigned char	Byte3;
    	unsigned char	Byte4;
    	unsigned char	Byte5;
    	unsigned char	Byte6;
    	unsigned char	Byte7;
    	unsigned char	Datalength;
    	DWORD	Identifier;
    
    };
    
    typedef struct tagCANMSG
    {
    	DWORD	dwIdentifier;
    	unsigned char byContent[8];
    	unsigned char byDatalength;
    
    }CANMSG;	
    
    extern "C" _declspec(dllexport) bool CAN_Write(CAN_MESSAGE *msgWrite)
    {
        	CANMSG cm;
    
    	cm.byDatalength=msgWrite->Datalength;
    	cm.dwIdentifier=msgWrite->Identifier;
    	cm.byContent[0]=msgWrite->Byte0;
    	cm.byContent[1]=msgWrite->Byte1;
    	cm.byContent[2]=msgWrite->Byte2;
    	cm.byContent[3]=msgWrite->Byte3;
    	cm.byContent[4]=msgWrite->Byte4;
    	cm.byContent[5]=msgWrite->Byte5;
    	cm.byContent[6]=msgWrite->Byte6;
    	cm.byContent[7]=msgWrite->Byte7;
    
    	cCAN.Write(&cm);
    	return 1;
    }
    

    Vielen Dank für eure Hilfe.
    Wenn jemand ein gutes Tutorial zu diesem Thema kennt währe mir auch sehr geholfen.

    Gruß spacehelix



  • Ich glaube, da kommt es auch drauf an, wie Du die dll im Hauptprogramm aufrufst. Poste mal den Code (zumindest die wichtigsten Stellen).

    http://www.henkessoft.de/C++/WinAPI/WinAPI Kapitel 1 bis 6/api6.htm



  • Hi,

    hier ist der Code meines Programms das die dll-Funktionen aufruft.
    der Aufruf der CanInit Funktion in der dll funktioniert.
    Wenn die Funktion "void CDummyDlg::OnButtonCANSend()" dann funktioniert es nicht.

    struct tagCANMSG2
    {
    	DWORD	dwIdentifier;
    	unsigned char	Byte0;
    	unsigned char	Byte1;
    	unsigned char	Byte2;
    	unsigned char	Byte3;
    	unsigned char	Byte4;
    	unsigned char	Byte5;
    	unsigned char	Byte6;
    	unsigned char	Byte7;
    	unsigned char	byDatalength;
    };	
    
    tagCANMSG2 CANmsg;
    typedef bool (*PFUNC_CANinit)(DWORD);
    typedef bool (*PFUNC_CanWrite)(tagCANMSG2);
    	HINSTANCE hm;
    	PFUNC_CanWrite CanWrite;
    
    void CDummyDlg::OnButton1() 
    {
    	bool returnValue;
    
    	hm = LoadLibrary(L"a.dll"); //Es wird UNICODE verwendet und deshalb muss der String für OS-Aufrufe mit "L" versehen werden (oder mit _T wenn #include <tchar.h> ) 
    
    	if (!hm) 
        {
        MessageBox(NULL, TEXT ("a.dll konnte nicht geladen werden"), MB_OK);
        }
    
     PFUNC_CANinit CanInit = (PFUNC_CANinit)GetProcAddress((HINSTANCE)hm, _T("CAN_Init")); //Es wird UNICODE verwendet und deshalb muss der String für OS-Aufrufe mit "L" versehen werden (oder mit _T wenn #include <tchar.h> )    
    	if (CanInit != NULL)
        {
    			returnValue=CanInit(250000); 
    					if (returnValue==false)
    				MessageBox(NULL, TEXT ("CAN Initialisierung Fehlgeschlagen"), MB_OK);
        }
    	else
    		MessageBox(NULL, TEXT ("Funktion CAN_Init nicht gefunden"), MB_OK);
    	//FreeLibrary((HMODULE)hm);
    }
    
    void CDummyDlg::OnButtonCANSend() 
    {
    	bool returnValue;
    	static bool x=false;
    
    	CANmsg.byDatalength=8;
    	CANmsg.dwIdentifier=0x000;
    	CANmsg.Byte0=1;
    	CANmsg.Byte1=2;
    	CANmsg.Byte2=3;
    	CANmsg.Byte3=4;
    	CANmsg.Byte4=5;
    	CANmsg.Byte5=6;
    	CANmsg.Byte6=7;
    	CANmsg.Byte7=8;
    
        if (x==false)
    	{
    		CanWrite = (PFUNC_CanWrite)GetProcAddress((HINSTANCE)hm, _T("CAN_Write")); //Es wird UNICODE verwendet und deshalb muss der String für OS-Aufrufe mit "L" versehen werden (oder mit _T wenn #include <tchar.h> )  
    		if (CanWrite != NULL)
    		{
    			x=true;
    			returnValue=CanWrite(CANmsg);
    
    			if (returnValue==false)
    				MessageBox(NULL, TEXT ("CAN Nachricht nicht gesendet"), MB_OK);
    		}
    		else
    			MessageBox(NULL, TEXT ("Funktion CAN_Init nicht gefunden"), MB_OK);
    	//FreeLibrary((HMODULE)hm);	
    	}
    }
    

    Gruß
    spacehelix



  • Vergleich doch mal die Definition von "struct tagCANMSG2" in deinem Anwendungsprogramm und "struct CAN_MESSAGE" in der DLL - fällt dir da ein Unterschied auf?

    (kleiner Tip: Strukt-Elemente werden in der Reihenfolge gespeichert, in der sie definiert sind)

    Edit: Und du solltest den Aufruf der DLL-Funktion auf dem "if(x==false)" Block rausnehmen, sonst macht die Funktion beim zweiten Aufruf gar nichts mehr.



  • Hi,

    das heißt also, das wenn ich die Elemente in meiner Struktur vertausche und die adresse der Struktur übergebe, kann das nicht funktionieren?

    Das mit dem x==false habe ich beim reinstellen ins Forum auch bemerkt ich bin aber noch garnicht soweit gekommen, trotzdem Danke.

    Ich werde díe Fehler jetzt mal korrigieren und schauen obs läuft.

    Gruß
    spacehelix



  • spacehelix schrieb:

    das heißt also, das wenn ich die Elemente in meiner Struktur vertausche und die adresse der Struktur übergebe, kann das nicht funktionieren?

    ja.

    tip:
    generell solltest du auch vermeiden die gleiche struktur zwei mal zu definieren.
    sprich denk nochmal über das design deiner dll nach oder ob du sie wirklich dynamsch laden möchtest.



  • spacehelix schrieb:

    das heißt also, das wenn ich die Elemente in meiner Struktur vertausche und die adresse der Struktur übergebe, kann das nicht funktionieren?

    Genau - die Funktion CAN_Write() in deiner DLL interpretiert den übergebenen Datenblock als "CAN_MESSAGE" - und dessen Elemente liegen etwas anders im Speicher als das, was du ihr übergeben hast.



  • Hi,

    die Funktion CAN_Write in der a.dll wird jetzt aufgerufen doch leider passiert beim Übergeben der Werte ein Fehler, bzw. es stehen erst garnicht die werte in meinen Strukturelementen.

    CANMSG cm;
    
    	cm.byContent[0]=msgWrite->Byte0; //hier passiert der Fehler
    	cm.byContent[1]=msgWrite->Byte1;
    	cm.byContent[2]=msgWrite->Byte2;
    	cm.byContent[3]=msgWrite->Byte3;
    	cm.byContent[4]=msgWrite->Byte4;
    	cm.byContent[5]=msgWrite->Byte5;
    	cm.byContent[6]=msgWrite->Byte6;
    	cm.byContent[7]=msgWrite->Byte7;
    	cm.byDatalength=msgWrite->Datalength;
    	cm.dwIdentifier=msgWrite->Identifier;
    

    Ich hab mir mit Quick Watch mal die Werte die in msgWrite->Byte0 bis Byte 2 angesehen dort steht drine:
    msgWrite->Byte0 = 49 '1'
    msgWrite->Byte1 = 144 '|' //dicker strich nicht Ascii Zeichen 124
    msgWrite->Byte2 = 231 'c' //nicht das normale c

    Nachdem ich die Zeile "cm.byContent[0]=msgWrite->Byte0;" ausführe kommt eine Fehlermeldung : First-chanch exeption in dummy.exe(A.DLL):0xC0000005: Access Violation.

    Was mache ich falsch ?

    Gruß Kevin



  • Hast du denn die Struktur in Ordnung gebracht? Oder verbiegst du immer noch zwei verschiedene Strukturen aufeinander?



  • Die Strukturen hab ich in Ordnung gebracht.

    Programm das die dll aufruft:

    struct tagCANMSG2
    {
    
    	unsigned char	Byte0;
    	unsigned char	Byte1;
    	unsigned char	Byte2;
    	unsigned char	Byte3;
    	unsigned char	Byte4;
    	unsigned char	Byte5;
    	unsigned char	Byte6;
    	unsigned char	Byte7;
    	unsigned char	byDatalength;
    	DWORD	dwIdentifier;
    };	
    
    tagCANMSG2 CANmsg;
    typedef bool (*PFUNC_CANinit)(DWORD);
    typedef bool (*PFUNC_CanWrite)(tagCANMSG2);
    static	HINSTANCE hm;
    	PFUNC_CanWrite CanWrite;
    
    void CDummyDlg::OnButtonCANSend() 
    {
    
    	bool returnValue;
    	static bool x=false;
    
    	CANmsg.Byte0=1;
    	CANmsg.Byte1=2;
    	CANmsg.Byte2=3;
    	CANmsg.Byte3=4;
    	CANmsg.Byte4=5;
    	CANmsg.Byte5=6;
    	CANmsg.Byte6=7;
    	CANmsg.Byte7=8;
    	CANmsg.byDatalength=8;
    	CANmsg.dwIdentifier=1;
    
        if (x==false)
    	{
    		CanWrite = (PFUNC_CanWrite)GetProcAddress((HINSTANCE)hm, _T("CAN_Write")); //Es wird UNICODE verwendet und deshalb muss der String für OS-Aufrufe mit "L" versehen werden (oder mit _T wenn #include <tchar.h> )  
    		if (CanWrite != NULL)
    		{
    			x=true;
    
    		}
    		else
    			MessageBox(NULL, TEXT ("Funktion CAN_Write nicht gefunden"), MB_OK);
    
    			returnValue=CanWrite(CANmsg);
    
    			if (returnValue==false)
    				MessageBox(NULL, TEXT ("CAN Nachricht nicht gesendet"), MB_OK);
    	//FreeLibrary((HMODULE)hm);	
    	}
    }
    

    dll:

    struct CAN_MESSAGE
    {
    
    	unsigned char	Byte0;
    	unsigned char	Byte1;
    	unsigned char	Byte2;
    	unsigned char	Byte3;
    	unsigned char	Byte4;
    	unsigned char	Byte5;
    	unsigned char	Byte6;
    	unsigned char	Byte7;
    	unsigned char	Datalength;
    	DWORD	Identifier;
    
    };	
    
    	static CCAN cCAN;
    
    extern "C" _declspec(dllexport) bool CAN_Write(CAN_MESSAGE *msgWrite)
    {
    
        	// TODO: Command line evaluation (port baud count)
    	//DWORD dwCount = 1000;
    	//CCAN cCAN;
    
    	//if(!cCAN.Init(_T("CID1:"),250000))
    	//	return 0;
    
     	CANMSG cm;
    
    	cm.byContent[0]=msgWrite->Byte0;
    	cm.byContent[1]=msgWrite->Byte1;
    	cm.byContent[2]=msgWrite->Byte2;
    	cm.byContent[3]=msgWrite->Byte3;
    	cm.byContent[4]=msgWrite->Byte4;
    	cm.byContent[5]=msgWrite->Byte5;
    	cm.byContent[6]=msgWrite->Byte6;
    	cm.byContent[7]=msgWrite->Byte7;
    	cm.byDatalength=msgWrite->Datalength;
    	cm.dwIdentifier=msgWrite->Identifier;
    
    	//do
    	//{		
    		//cm.byContent[0]=(BYTE)dwCount%0xff;
    		//cm.dwIdentifier=dwCount;
    		cCAN.Write(&cm);
    		//Sleep(100);
    	//}while(dwCount--);
    
    return 1;
    }
    

    Ich habe in der dll testweise mal feste werte Vorgegeben siehe unten dann sendet es mir die Daten über den CAN-Bus.

    cm.byContent[0]=1;//msgWrite->Byte0;
    	cm.byContent[1]=2;//msgWrite->Byte1;
    	cm.byContent[2]=3;//msgWrite->Byte2;
    	cm.byContent[3]=4;//msgWrite->Byte3;
    	cm.byContent[4]=5;//msgWrite->Byte4;
    	cm.byContent[5]=6;//msgWrite->Byte5;
    	cm.byContent[6]=7;//msgWrite->Byte6;
    	cm.byContent[7]=8;//msgWrite->Byte7;
    	cm.byDatalength=8;//msgWrite->Datalength;
    	cm.dwIdentifier=0;//msgWrite->Identifier;
    

    Gruß spacehelix



  • adresse übergeben

    CanWrite(&CANmsg);
    


  • Hi,

    hab ich auch schon probiert, da kommt aber folgende Fehlermeldung.

    error C2664: 'bool (struct tagCANMSG2)' : cannot convert parameter 1 from 'struct tagCANMSG2 *' to 'struct tagCANMSG2'

    Was ich mir irgendwie hergeleitet habe, ist folgender Code:

    typedef bool (*PFUNC_CANinit)(DWORD);
    typedef bool (*PFUNC_CanWrite)(tagCANMSG2);

    vielleicht ist hier schon der Fehler drin und es müsste heißen
    typedef bool (*PFUNC_CanWrite)(*tagCANMSG2); oder so ähnlich

    Ich weis aber überhaupt nicht warum und weshalb ich das so geschrieben hab. Vieleicht kann da ja mal jemand ein Kommentar dazu abgeben.

    Ich nehme an: "typdef bool" weil die Funktion die in der dll aufgerufen wird den Rückgabewert bool hat. Weiter weis ich net.

    Gruß spacehelix



  • sollte natürlich so sein wie die funktion die du exportierst.

    typedef bool (*PFUNC_CanWrite)(tagCANMSG2*);
    

    [edit]
    ➡ http://www.newty.de/fpt/index.html



  • Hi,

    Danke an allen die mir geholfen haben dieses Problem zu lösen. Wie Ihr wahrscheinlich gemerkt habt, habe ich noch sehr wenig Erfahrung mit C++. Ich hoffe das wird sich schnell ändern. Deshalb finde ich es gut das es dieses Forum gibt.

    Also Vielen Dank

    Gruß spacehelix


Log in to reply