virtual funktion in bibliothek LNK2019



  • Moin,

    schreibe im moment http libary möchte diese jetzt auf windows potieren habe nur eine schwerigkeit festgsstellt.

    Wenn ich eine virtuelle funktion definiere und diese erst ausserhalb der bibliothek nutzen möchte bekomme ich LNK2019 gibt es die Möglichkeit unter Visualstudio diese extern zu deklarieren so das er keinen linking error mehr erzeugt. Unter clang und gcc geht das Problem los also denke ich gibt auch eine möglichkeit für vs2015.

    Der code liegt auf github:
    https://github.com/Tuxist/libhttppp

    Severity	Code	Description	Project	File	Line	Suppression State
    Error	LNK2019	unresolved external symbol "public: virtual void __cdecl libhttppp::Queue::RequestEvent(class libhttppp::Connection *)" (?RequestEvent@Queue@libhttppp@@UEAAXPEAVConnection@2@@Z) referenced in function "public: __cdecl libhttppp::Queue::Queue(class libhttppp::ServerSocket *)" (??0Queue@libhttppp@@QEAA@PEAVServerSocket@1@@Z)	http++	C:\Users\Player\Source\Repos\libhttppp\build_win\src\iocp.obj	1
    


  • So wie es im Code aussieht, hat dein Problem (noch) nichts mit DLL zu tun. Vielmehr deklarierst du void libhttppp::Queue::RequestEvent(class libhttppp::Connection *) als virtuelle Funktion, lieferst aber keine Definition (Implementation) dazu.

    Falls du vor hast diese Funktion jeweils nur in den abgeleiteten Klasse zu definieren, dann musst du die Funktion als pure virtual deklarieren.

    Das geht so (aus event.hpp ) - beachte das = 0:

    namespace libhttppp {
    	class Queue : public ConnectionPool {
    	public:
    		Queue(ServerSocket *serversocket);
    		virtual ~Queue();
    		virtual void RequestEvent(Connection *curcon) = 0;
      private:
        HTTPException       _httpexception;
      };
    }
    

    Natürlich kannst du, sofern das sinnvoll ist, auch eine Default-Implementierung bereitstellen (entweder gleich im Header oder in event.cpp ).

    BTW: Die Datei event.hpp sollte wohl queue.hpp heissen.

    Wenn du die Bibliothek als DLL benutzen möchtest, musst du noch die entsprechenden Symbole exportieren. Dazu gibt es mehrere Möglichkeiten, hier ein Dokument von MS: https://msdn.microsoft.com/en-us/library/z4zxe9k8.aspx



  • hat jetzt funktioniert danke leider bekomme ich dann neue build errors

    #include "exception.h"
    #include "socket.h"
    #include "connections.h"
    
    #ifndef QUEUE_H
    #define QUEUE_H
    
    namespace libhttppp {
    	class Queue : public ConnectionPool {
    	public:
    		Queue(ServerSocket *serversocket);
    		virtual ~Queue();
    #ifdef MSVC
    		__declspec(dllexport) virtual void RequestEvent(Connection *curcon)=0;
    #else
    		virtual void RequestEvent(Connection *curcon)=0;
    #endif
      private:
        HTTPException       _httpexception;
      };
    }
    
    #endif
    


  • habe den aufbau nochmal genauer definiert das ganze funktioniert unter gcc und clang aber leider nicht unter visualstudio es muss doch eine möglichkeit geben so etwas zu implementieren. Bin auch offen für andere vorschläge mit static habe ich es auch schon versucht ohne erfolg. Brauche einfach nur die möglichkeit eine funktion ausserhalb der klasse zu definieren um sie dann innerhalb der klasse aufzurufen.

    definition der Funktion innerhalb der library

    #ifndef QUEUE_H
    #define QUEUE_H
    
    namespace libhttppp {
    	class Queue : public ConnectionPool {
    	public:
    		Queue(ServerSocket *serversocket);
    		virtual ~Queue();
    #ifdef MSVC
    		__declspec(dllexport) virtual void RequestEvent(Connection *curcon);
    #else
    		virtual void RequestEvent(Connection *curcon);
    #endif
      private:
        HTTPException       _httpexception;
      };
    }
    
    #endif
    

    Aufruf der Funktion innerhalb der library

    Queue::Queue(ServerSocket *socket) : ConnectionPool(socket) {
      HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0); // equals epoll_create
      CreateIoCompletionPort(socket, iocp, 0, 0); // equals epoll_ctl(EPOLL_CTL_ADD)
    
      for(;;){
    //         if(GetQueuedCompletionStatus(iocp, &number_bytes, &key, &o, INFINITE)) // equals epoll_wait()
    //         do_something();
    	  Connection *curcon;
    	  RequestEvent(curcon);
      }
    }
    

    ausserhalb der library

    void libhttppp::Queue::RequestEvent(libhttppp::Connection *curcon){
       try{
         std::cerr << "Parse Request\n";
         libhttppp::HttpRequest curreq;
         curreq.parse(curcon);
         std::cerr << "Send answer\n";
         sendResponse(curcon,&curreq);
       }catch(HTTPException &e){
         std::cerr << e.what() << "\n";
         throw e;
       }
    }
    


  • Was heisst "funktioniert nicht"? Bitte Fehlermeldungen zeigen, erwartetes/tatsächliches Verahlten beschreiben, etc.

    Was heisst "so etwas zu implementieren"? Was möchtest du implementieren? Auch unter VS geht ziemlich alles was mit anderen Compilern auch geht.

    Tuxist schrieb:

    Aufruf der Funktion innerhalb der library ...
    ausserhalb der library ...

    Welche Funktion meinst du?



  • RequestEvent(Connection *curcon) welche ich nicht pure virtual setzten kann da Sie innerhalb der klasse definiert und aufgerufen wird so wie außerhalb der klasse implementiert wird. Am einfachsten den Code von github ziehen und im ordner test nach der Implantation schauen. Die statische lib baut er auch aber bei der dll streikt er.



  • Alles klar, danke.



  • Habe mich in den msdn Form schlau gemacht so wie ich es vor hatte kann es der msvc nicht. Habe andere Möglichkeit aufgezeigt bekommen und implementiert.

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/94ea6e32-ad3c-4a5a-b5ac-bb84f785fc3b/lnk2019-external-virtual-function?forum=vcgeneral


Log in to reply