Anfängerproblem mit DLL-Einbindung, Zeigern und Datentyp-Konvertierung



  • Hallo,

    ich muss für ein älteres Prüfsystem, zum Einbinden PCI-CAN-Karte, eine Hilfs-Dll erstellen, mit der ich einige Inkompatibilitäten (struct etc.) umgehen muss. Zum ansprechen der Hardware dient mir eine Dll (GPxi3051w.dll) des Herstellers. Zum testen habe ich erst einmal eine Consolen-Applikation erstellt. Was C(++|#) angeht habe ich (fast) keinerlei Erfahrungen. Hier erst einmal der Code der Cpp-Datei:

    #include "stdafx.h"
    #include "GPxi3051w.h"
    #include <stdio.h>
    #include <iostream>
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
    	GPxi3051_StructDriverInfo DriverInfo;
    	int errornr;
    	errornr= GPxi3051_GetDriverInfo(*DriverInfo);
    	cout <<"Version:" << DriverInfo.Version << "\n";
    	cout <<"SW_XILINX:" << DriverInfo.SW_XILINX << "\n";
    	cout <<"GeoAddress:" << DriverInfo.GeoAddress << "\n";
    	cout <<"SerialNumber:" << DriverInfo.SerialNumber << "\n";
    	cout <<"Revision:" << DriverInfo.Revision << "\n";
    	cout <<"Fehler:" << errornr << "\n";
    	return 0;
    }
    

    und der Code der Header-Datei

    #ifndef PXI3051_API_HEADER
    #define PXI3051_API_HEADER
    
    /*------------------------------------------------------------------*/
    /* Defines                                                          */					
    /*------------------------------------------------------------------*/
    #define DEV_MAX                   12
    
    /*------------------------------------------------------------------*/
    /* Typedefs															*/					
    /*------------------------------------------------------------------*/
    typedef struct
      {
      unsigned long Version;
      unsigned long DevCount;
      unsigned long SW_XILINX[DEV_MAX];
      unsigned long GeoAddress[DEV_MAX];
      unsigned long SerialNumber[DEV_MAX];
      unsigned long Revision[DEV_MAX];
      } GPxi3051_StructDriverInfo;
    
    /*------------------------------------------------------------------*/
    /* Functions														*/					
    /*------------------------------------------------------------------*/
    
    int __declspec ( dllexport ) __stdcall GPxi3051_GetDriverInfo(GPxi3051_StructDriverInfo *pDriverInfo);
    int __declspec ( dllexport ) __stdcall GPxi3051_DLL_Version(unsigned long *pVersion);
    int __declspec ( dllexport ) __stdcall GPxi3051_ResetPort(unsigned long card, unsigned long port);
    int __declspec ( dllexport ) __stdcall GPxi3051_DpramWriteInstruction(unsigned char data[], unsigned long length);
    int __declspec ( dllexport ) __stdcall GPxi3051_DpramReadResponse(unsigned long card, unsigned long port, unsigned char data[], unsigned long *length);
    int __declspec ( dllexport ) __stdcall GPxi3051_DpramReadMonitor(unsigned long card, unsigned long port,void *data, unsigned long *length);
    int __declspec ( dllexport ) __stdcall GPxi3051_XilinxDownload(unsigned long card, char *pFileName);
    int __declspec ( dllexport ) __stdcall GPxi3051_XilinxWriteData(unsigned char data[], unsigned long length);
    
    #endif
    

    Und meine drei Probleme
    1. Wie wird eine DLL in VC++6 eingebunden? Ich habe keine LIB-Datei, kenne aber die Funktionen (siehe Header-Datei). Ich habe alles was ich im Internet und im MSDN gefunden habe ausprobiert, allerdings ohne Erfolg.
    2. Wo finde ich im MSDN oder Internet eine Übersicht über die Konvertierung von Datentypen in C++?
    3. Beim Erstellen der Anwendung kommt es zu folgender Fehlermeldung:

    D:\Users\Pierre\Eigene Dateien\Visual C\can_dll v2\can_dll v2.cpp(16) : error C2100: Zeigeroperation ungueltig
    D:\Users\Pierre\Eigene Dateien\Visual C\can_dll v2\can_dll v2.cpp(16) : error C2664: 'GPxi3051_GetDriverInfo' : Konvertierung des Parameters 1 von 'GPxi3051_StructDriverInfo' in 'GPxi3051_StructDriverInfo *' nicht möglich
            Kein benutzerdefinierter Konvertierungsoperator verfügbar, der diese Konvertierung durchführen kann, oder der Operator kann nicht aufgerufen werden
    

    Was habe ich hier Falsch gemacht?

    Mit freundlichen Grüßen

    PierreOne



  • Versuch mal:

    errornr= GPxi3051_GetDriverInfo(&DriverInfo);
    


  • oder versuch mal :

    GPxi3051_StructDriverInfo *DriverInfo;
    


  • Hallo,

    Was ist eigentlich der Unterschied zwischen "GPxi3051_GetDriverInfo(&DriverInfo)" und GPxi3051_GetDriverInfo(*DriverInfo). Natürlich habe ich es ausprobiert, allerdings führte es zu der Fehlermeldung:

    Temporäre Dateien und Ausgabedateien für "can_dll v2 - Win32 Debug" werden gelöscht.
    --------------------Konfiguration: can_dll v2 - Win32 Debug--------------------
    Kompilierung läuft...
    StdAfx.cpp
    Kompilierung läuft...
    can_dll v2.cpp
    Linker-Vorgang läuft...
    can_dll v2.obj : error LNK2001: Nichtaufgeloestes externes Symbol "int __stdcall GPxi3051_GetDriverInfo(struct GPxi3051_StructDriverInfo *)" (?GPxi3051_GetDriverInfo@@YGHPAUGPxi3051_StructDriverInfo@@@Z)
    Debug/can_dll v2.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise
    Fehler beim Ausführen von link.exe.
    
    can_dll v2.exe - 2 Fehler, 0 Warnung(en)
    

    Deshalb habe ich mit pexports eine def-Datei erstellt und eingebunden.

    LIBRARY GPxi3051w.dll
    EXPORTS
    GPxi3051_DLL_Version    	@1
    GPxi3051_DpramReadMonitor	@6
    GPxi3051_DpramReadResponse	@5
    GPxi3051_DpramWriteInstruction	@4
    GPxi3051_GetDriverInfo  	@2
    GPxi3051_ReadWriteSpezial	@14
    GPxi3051_ResetPort      	@7
    GPxi3051_XilinxDownload 	@3
    GPxi3051_XilinxWriteData	@15
    

    Die Fehlermeldung lautet dann:

    Temporäre Dateien und Ausgabedateien für "can_dll v2 - Win32 Debug" werden gelöscht.
    --------------------Konfiguration: can_dll v2 - Win32 Debug--------------------
    Kompilierung läuft...
    StdAfx.cpp
    Kompilierung läuft...
    can_dll v2.cpp
    Linker-Vorgang läuft...
       Bibliothek Debug/can_dll v2.lib und Objekt Debug/can_dll v2.exp wird erstellt
    can_dll v2.exp : warning LNK4070: Die Direktive /OUT:GPxi3051w.dll in .EXP weicht vom Ausgabedateinamen "Debug/can_dll v2.exe" ab; Direktive wird ignoriert
    Debug/can_dll v2.exe : warning LNK4086: Einsprungpunkt "_mainCRTStartup" ist nicht __stdcall mit 12 Bytes an Argumenten; Anwendung kann vielleicht nicht ausgefuehrt werden
    can_dll v2.obj : error LNK2001: Nichtaufgeloestes externes Symbol "int __stdcall GPxi3051_GetDriverInfo(struct GPxi3051_StructDriverInfo *)" (?GPxi3051_GetDriverInfo@@YGHPAUGPxi3051_StructDriverInfo@@@Z)
    Debug/can_dll v2.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise
    Fehler beim Ausführen von link.exe.
    
    can_dll v2.exe - 2 Fehler, 2 Warnung(en)
    

    Der zweite Vorschlag ist leider ungeeignet, da ich wissen muss ob alles geklappt hat.

    MfG

    PierreOne



  • du musst auch beim zweiten vorschlage die klammern weg lassen!

    GPxi3051_StructDriverInfo *DriverInfo;
    

    und zwar will ich nicht das du den * vor DriverInfo bei der Parameter übergabe in der Funktion

    errornr= GPxi3051_GetDriverInfo(.....);
    

    , sonder
    bei der deklaration der DriverInfo (erste zeile bei dir in main)

    und bei den funktionaufruf schreibst dann:

    errornr= GPxi3051_GetDriverInfo(DriverInfo);
    

    so mein ich:

    #include "stdafx.h" 
    #include "GPxi3051w.h" 
    #include <stdio.h> 
    #include <iostream> 
    
    using namespace std; 
    
    int main(int argc, char* argv[]) 
    { 
        GPxi3051_StructDriverInfo *DriverInfo; 
        int errornr; 
        errornr= GPxi3051_GetDriverInfo(DriverInfo); 
        cout <<"Version:" << DriverInfo.Version << "\n"; 
        cout <<"SW_XILINX:" << DriverInfo.SW_XILINX << "\n"; 
        cout <<"GeoAddress:" << DriverInfo.GeoAddress << "\n"; 
        cout <<"SerialNumber:" << DriverInfo.SerialNumber << "\n"; 
        cout <<"Revision:" << DriverInfo.Revision << "\n"; 
        cout <<"Fehler:" << errornr << "\n"; 
        return 0; 
    }
    


  • Hallo,

    das habe ich natürlich sofort ausprobiert, allerdings folgten andere Fehlermeldungen. Ich vermute, dass meine DLL-Einbindung fehlerhaft ist.
    Deshalb habe ich noch einmal von vorne begonnen.
    Ich habe deshalb mit “dumpbin /exports /out:exports.txt GPxi3051w.dll“ eine exports.txt mit folgendem Inhalt erstellt.

    Dump of file GPxi3051w.dll
    
    File Type: DLL
    
      Section contains the following exports for GPxi3051w.dll
    
        00000000 characteristics
        4402DFAE time date stamp Mon Feb 27 12:17:02 2006
            0.00 version
               1 ordinal base
              15 number of functions
               9 number of names
    
        ordinal hint RVA      name
    
              1    0 0000133D GPxi3051_DLL_Version
              6    1 00001587 GPxi3051_DpramReadMonitor
              5    2 00001531 GPxi3051_DpramReadResponse
              4    3 000014A6 GPxi3051_DpramWriteInstruction
              2    4 000012CF GPxi3051_GetDriverInfo
             14    5 00001637 GPxi3051_ReadWriteSpezial
              7    6 000015F0 GPxi3051_ResetPort
              3    7 00001358 GPxi3051_XilinxDownload
             15    8 00001683 GPxi3051_XilinxWriteData
    
      Summary
    
            4000 .data
            1000 .rdata
            1000 .reloc
            5000 .text
    

    Daraus habe ich dann eine “GPxi3051w.def“ mit folgendem Inhalt erstellt

    LIBRARY "GPxi3051w.dll"
    EXPORTS
    GPxi3051_DLL_Version @1
    GPxi3051_DpramReadMonitor @6
    GPxi3051_DpramReadResponse @5
    GPxi3051_DpramWriteInstruction @4
    GPxi3051_GetDriverInfo @2
    GPxi3051_ReadWriteSpezial @14
    GPxi3051_ResetPort @7
    GPxi3051_XilinxDownload @3
    GPxi3051_XilinxWriteData @15
    

    Jetzt habe ich ein leeres Consolen-Projekt erstellt die "GPxi3051w.def" und eine Header-Datei mit folgendem Inhalt hizugefügt.

    /*------------------------------------------------------------------*/
    /* Defines                                                          */					
    /*------------------------------------------------------------------*/
    #define DEV_MAX                   12
    
    /*------------------------------------------------------------------*/
    /* Typedefs															*/					
    /*------------------------------------------------------------------*/
    typedef struct
      {
      unsigned long Version;
      unsigned long DevCount;
      unsigned long SW_XILINX[DEV_MAX];
      unsigned long GeoAddress[DEV_MAX];
      unsigned long SerialNumber[DEV_MAX];
      unsigned long Revision[DEV_MAX];
      } GPxi3051_StructDriverInfo;
    
    /*------------------------------------------------------------------*/
    /* Functions														*/					
    /*------------------------------------------------------------------*/
    
    #define DllImport   __declspec( dllimport )
    
    DllImport int GPxi3051_DLL_Version(unsigned long *pVersion);
    DllImport int GPxi3051_DpramReadMonitor(unsigned long card, unsigned long port,void *data, unsigned long *length);
    DllImport int GPxi3051_DpramReadResponse(unsigned long card, unsigned long port, unsigned char data[], unsigned long *length);
    DllImport int GPxi3051_DpramWriteInstruction(unsigned char data[], unsigned long length);
    DllImport int GPxi3051_GetDriverInfo(GPxi3051_StructDriverInfo *pDriverInfo);
    DllImport int GPxi3051_ResetPort(unsigned long card, unsigned long port);
    DllImport int GPxi3051_XilinxDownload(unsigned long card, char *pFileName);
    DllImport int GPxi3051_XilinxWriteData(unsigned char data[], unsigned long length);
    

    Zur Vollständigkeit auch noch das Programm

    #include "stdafx.h"
    #include "GPxi3051w.h"
    
    int main(int argc, char* argv[])
    {
    	int errornr;
    	errornr = GPxi3051_ResetPort(1, 1);
        return TRUE;
    }
    

    Beim erstellen wird folgende Fehlermeldung ausgegeben.

    Temporäre Dateien und Ausgabedateien für "tcan - Win32 Debug" werden gelöscht.
    --------------------Konfiguration: tcan - Win32 Debug--------------------
    Kompilierung läuft...
    StdAfx.cpp
    tcan.cpp
    Linker-Vorgang läuft...
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_DLL_Version
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_DpramReadMonitor
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_DpramReadResponse
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_DpramWriteInstruction
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_GetDriverInfo
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_ReadWriteSpezial
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_ResetPort
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_XilinxDownload
    GPxi3051w.def : error LNK2001: Nichtaufgeloestes externes Symbol GPxi3051_XilinxWriteData
    Debug/tcan.lib : fatal error LNK1120: 9 unaufgeloeste externe Verweise
    LINK : fatal error LNK1141: Fehler bei der Erstellung der Exportdatei
    Fehler beim Ausführen von link.exe.
    
    tcan.exe - 11 Fehler, 0 Warnung(en)
    

    Was habe ich falsch gemacht?

    Mit freundlichen Grüßen

    PierreOne


Anmelden zum Antworten