Einbindung von DLL/Header in Forms Anwendung



  • Hallo zusammen,

    ich habe für eine Motorsteuerung folgende Dateien zur Verfügung, die ich in einer Forms-Anwendung verwenden muss: Definitions.h, EposCmd.dll sowie EposCmd.lib (aus VC++ 2005).
    Alle Dateien sind im Projektordner, die lib-Datei ist in den Projekteigenschaften->Linker->zus.Abhängigkeiten eingetragen und die Headerdatei habe ich in Form1.h eingebunden.

    #pragma once
    #include "Definitions.h"
    namespace Testform {
    ...
    

    Weiteren Code habe ich noch nicht eingefügt, aber beim Kompilieren erhalte ich folgende Fehler:

    1>Testform.cpp(4): error C2855: Die Befehlszeilenoption '/clr:pure' steht in Konflikt mit der vorkompilierten Header-Datei

    sowie

    1>c:\dokumente und einstellungen\sm\eigene dateien\visual studio 2010\projects\testform\Definitions.h(100): error C3389: __declspec(dllexport) kann bei /clr:pure oder /clr:safe nicht verwendet werden.

    Daraufhin habe ich die Einstellung für Common Language Runtime-Unterstützung auf /clr geändert (Standard /clr:pure). Es hat aber nicht geholfen.
    Bei meinem Konsolenprogramm (ebenfalls mit VC++ 2010 Express erstellt) funktioniert das Einbinden der Dateien und der Zugriff auf die Funktionen aus der Bibliothek problemlos. Ich weiss nicht was ich falsch mache. Diverse Beiträge im Forum habe ich diesbezüglich auch schon gelesen, aber irgendwie bringt mich das nicht weiter. Wieso funktionierts beim Konsolenprogramm und bei der Forms-Anwendung nicht?
    Ich wäre sehr froh, wenn Ihr mir helfen könntet.

    Hier noch ein Auszug aus der Definitions.h. Vielleicht hilft Euch das weiter:

    #ifndef _WINDOWS_
    #include <windows.h>
    #endif
    
    // --------------------------------------------------------------------------
    //                            IMPORTED FUNCTIONS PROTOTYPE
    // --------------------------------------------------------------------------
    
    // INITIALISATION FUNCTIONS
        #define Initialisation_DllExport            extern "C" __declspec( dllexport )
        #define HelpFunctions_DllExport             extern "C" __declspec( dllexport )
    // CONFIGURATION FUNCTIONS
        #define Configuration_DllExport             extern "C" __declspec( dllexport )
    // OPERATION FUNCTIONS
        #define Status_DllExport                    extern "C" __declspec( dllexport )
        #define StateMachine_DllExport              extern "C" __declspec( dllexport )
        #define ErrorHandling_DllExport             extern "C" __declspec( dllexport )
        #define MotionInfo_DllExport                extern "C" __declspec( dllexport )
        #define ProfilePositionMode_DllExport       extern "C" __declspec( dllexport )
        #define ProfileVelocityMode_DllExport       extern "C" __declspec( dllexport )
        #define HomingMode_DllExport                extern "C" __declspec( dllexport )
        #define InterpolatedPositionMode_DllExport  extern "C" __declspec( dllexport )
        #define PositionMode_DllExport              extern "C" __declspec( dllexport )
        #define VelocityMode_DllExport              extern "C" __declspec( dllexport )
        #define CurrentMode_DllExport               extern "C" __declspec( dllexport )
        #define MasterEncoderMode_DllExport         extern "C" __declspec( dllexport )
        #define StepDirectionMode_DllExport         extern "C" __declspec( dllexport )
        #define InputsOutputs_DllExport             extern "C" __declspec( dllexport )
    // DATA RECORDING FUNCTIONS
        #define DataRecording_DllExport             extern "C" __declspec( dllexport )
    // LOW LAYER FUNCTIONS
        #define CanLayer_DllExport                  extern "C" __declspec( dllexport )
    
    /*************************************************************************************************************************************
    * INITIALISATION FUNCTIONS
    *************************************************************************************************************************************/
    
    //Communication
        Initialisation_DllExport HANDLE __stdcall VCS_OpenDevice(char* DeviceName, char* ProtocolStackName, char* InterfaceName, char* PortName, DWORD* pErrorCode);
        Initialisation_DllExport HANDLE __stdcall VCS_OpenDeviceDlg(DWORD* pErrorCode);
        Initialisation_DllExport BOOL __stdcall VCS_SetProtocolStackSettings(HANDLE KeyHandle, DWORD Baudrate, DWORD Timeout, DWORD* pErrorCode);
        Initialisation_DllExport BOOL __stdcall VCS_GetProtocolStackSettings(HANDLE KeyHandle, DWORD* pBaudrate, DWORD* pTimeout, DWORD* pErrorCode);
        Initialisation_DllExport BOOL __stdcall VCS_FindDeviceCommunicationSettings(HANDLE *pKeyHandle, char *pDeviceName, char *pProtocolStackName, char *pInterfaceName, char *pPortName, WORD SizeName, DWORD *pBaudrate, DWORD *pTimeout, WORD *pNodeId, int DialogMode, DWORD *pErrorCode);
        Initialisation_DllExport BOOL __stdcall VCS_CloseDevice(HANDLE KeyHandle, DWORD* pErrorCode);
        Initialisation_DllExport BOOL __stdcall VCS_CloseAllDevices(DWORD* pErrorCode);
    ....
    


  • __declspec(dllexport) macht beim Einbinden einer Library keinen Sinn - das müsste wohl __declspec(dllimport) heissen.

    Ein Möglichkeit wäre das von Hand abzuändern. Allerdings vermute ich eher, dass der Header schon korrekt ist und halt noch ein #define fehlt. Gibts in der Header Datei irgendwo __declspec(dllimport)?

    Edit:
    Ist der Header und die Library von Dir? Ev. war ich etwas voreilig mit der Vermutung, dass der Header schon korrekt ist. Ich nahm an, die Library stammt vom Motorenhersteller.

    Edit2:
    Typischerweise sieht es so aus:

    #ifdef MY_LIBRARY_EXPORTS
       #define MY_LIBRARY_API __declspec(dllexport)
    #else
       #define MY_LIBRARY_API __declspec(dllimport)
    #endif
    
    extern "C"
    {
       MY_LIBRARY_API HANDLE __stdcall VCS_OpenDevice(char* DeviceName, ...);
    }
    

    Das extern "C" kann natürlich auch in das #define raufgenommen werden.

    Die Library definiert einfach MY_LIBRARY_EXPORTS und exportiert somit Symbole - der Benutzer definiert dann MY_LIBRARY_EXPORTS NICHT und importiert somit die Symbole.



  • Hallo theta,

    danke erstmal für Deine Hilfe. Die Headerdatei ist orginal vom Hersteller. Eine Importanweisung "__declspec(dllimport)" ist nicht vorhanden.

    Mittlerweile funktioniert das Grundprogramm mit der eingebundenen dll. Was ich letztendlich gemacht habe ist folgendes:
    1. Alle drei files EposCmd.lib, EposCmd.dll und Definitions.h ins Projektverzeichnis kopiert.
    2. Projekteigenschaften..Linker..bei zus. Abhängigkeiten "EposCmd.lib" eingetragen
    3. Alle .cpp Dateien einschl. Projekt in Projekteigenschaften..Konfig..Allgemein die Common Language Runtime-Unterstützung auf /clr umgestellt (Standard /clr:pure)
    4. Projekteigenschaften..C/C++..vorkompilierte Header..->nicht verwenden
    5. In Form1.h #include "Definitions.h" eingefügt.

    Zusätzlich habe ich vom Hersteller inzwischen ein Beispielprogramm mit einer anderen dll (EposCmd.net.dll) bekommen, die folgendermassen eingebunden ist (alle anderen Projekteigenschaften sind auf Standard:

    #pragma once
    
    #using <EposCmd.Net.dll>
    
    namespace epos2 {
    
    	using namespace System;
    	using namespace System::ComponentModel;
    	using namespace System::Collections;
    	using namespace System::Windows::Forms;
    	using namespace System::Data;
    	using namespace System::Drawing;
    	using namespace EposCmd::Net;
    	using namespace EposCmd::Net::DeviceCmdSet::Operation;
    
    	/// <summary>
    	/// Summary for Form1
    	/// </summary>
    	public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
    		Form1(void)
    		{
    			InitializeComponent();
    			//
    			//TODO: Add the constructor code here
    			//
    		}
    ...usw.
    

    Ich weiss nur noch nicht, welche von beiden Lösungen ich verwenden werde. Die erstere bevorzuge ich, da ich so alle Funktionen, die ich für ein Testkonsolenprogramm (in einer Klasse) geschrieben habe weiterhin verwenden kann.



  • #using <EposCmd.Net.dll>
    

    #using ist die Direktive um .NET Assemblies einzubinden. Das ist sehr gut, denn das bedeutet, der Herrsteller hat schon eine .NET Library, bzw. eine Kapselung vorgenommen. Da Du mit C++/CLI programmierst (was eine .NET Sprache ist) ist es korrekt #using und somit auch die EposCmd.Net.dll zu benutzen.

    Edit:
    Nur als Hinweis.. wenn Du das .NET Assembly einbindest brauchst Du die *.h und *.lib nicht! Die EposCmd.dll wird ev. von der EposCmd.Net.dll benötigt - findest Du aber schnell raus.


Anmelden zum Antworten