Thread: Explicit DLL loading

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    3

    Explicit DLL loading

    I'm trying to get a reference to a class inside my dll, from main.cpp.

    I'm using this tutorial to do it.

    The problem is with the client code,

    Code:
    //============================================================
    //Client code
    
    
    //How to load the interface and call functions
    
    GETINTERFACE    pfnInterface=0; //pointer to GetMyInterface function
    I_MyInterface * pInterface  =0; //pointer to MyInterface struct
    
    HINSTANCE hMyDll = ::LoadLibrary("myinterface.dll");
    
    if(hMyDll != NULL)
    {
       //Get the functions address
       pfnInterface= (GETINTERFACE)::GetProcAddress(hMyDll,"GetMyInterface");
    
       //Release Dll if we werent able to get the function
       if(pfnInterface == 0)   
       {
          ::FreeLibrary(hMyDll);
          return;
       }
    
       //Call the Function
       HRESULT hr = pfnInterface(&pInterface);
       
       //Release if it didnt work
       if(FAILED(hr))   
       {   
          ::FreeLibrary(hMyDll);
          return;
       }
    
       //Interface was loaded, we can now call functions
       pInterface->Init(1);
       pInterface->DoStuff();
       pInterface->Release();
    
       //How to release the interface
    
       FREEINTERFACE pfnFree = (FREEINTERFACE )::GetProcAddress(hMyDll,"FreeMyInterface");
       if(pfnFree != 0)
          pfnFree(&hMyDll);
    
       //Release the DLL if we dont have any use for it now
       ::FreeLibrary(hMyDll);
    }
    specifically with this part:

    Code:
    GETINTERFACE    pfnInterface=0; //pointer to GetMyInterface function
    I_MyInterface * pInterface  =0; //pointer to MyInterface struct
    I get a bunch of errors because GETINTERFACE isn't declared anywhere (except inside the DLL).

    I'm not sure how to declare it, and I don't want to include the header for the dll because it has to be linked at run time and not at compile time. The tutorial left that part out.

    Please let me know if you know how to declare GETINTERFACE. Thanks.

  2. #2
    Registered User
    Join Date
    Aug 2007
    Posts
    81
    You would have a header file that declares GETINTERFACE as extern, included by both the dll and the client, I think.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Including a header will not link your dll to your program, so including it will not do any harm.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Registered User
    Join Date
    May 2008
    Posts
    3
    Hmm... Doesn't seem to be working....

    What changes would I have to make to the following to get it to work:

    This is in my test solution called "dll", which has 2 different projects in it.

    This is the entry point project, which just has main.cpp plus some std stuff:

    Code:
    // dll.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "conio.h"
    #include <iostream>
    #include <windows.h>
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	GETINTERFACE pfnInterface=0;
    	IMyInterface *pInterface =0;
    
    	HINSTANCE hMyDLL = ::LoadLibrary("myDLL.dll");
    
    	if( hMyDLL )
    	{
    		pfnInterface = (GETINTERFACE)::GetProcAddress(hMyDLL, "GetInterface");
    		if( !pfnInterface )
    		{
    			::FreeLibrary(hMyDLL);
    			std::cout<<"getinterface failed\n";
    			getch();
    			return 1;
    		}
    
    		HRESULT hr = pfnInterface( &pInterface );
    
    		if( FAILED(hr) )
    		{
    			::FreeLibrary(hMyDLL);
    			std::cout<<"fn call failed\n";
    			getch();
    			return 1;
    		}
    
    		pInterface->Init(1);
    		pInterface->DoStuff();
    		pInterface->Release();
    
    		FREEINTERFACE pfnFree = (FREEINTERFACE)::GetProcAddress(hMyDLL, "FreeInterface");
    		if(pfnFree != 0)
    			pfnFree(&pInterface);
    
    		::FreeLibrary(hMyDLL);
    	}
    
    	_getch();
    	return 0;
    }
    This is the other project, with 4 different files in it:

    This is the file which has the interfaces, etc.
    Code:
    #ifndef __DLLSRC_H__
    #define __DLLSRC_H__
    #include <windows.h>
    struct IMyInterface
    {
    	virtual bool Init(int params) = 0;
    	virtual bool Release() = 0;
    	virtual bool DosTuff() = 0;
    };
    
    extern "C"
    {
    	HRESULT GetInterface( IMyInterface **pInterface );
    	typedef HRESULT (*GETINTERFACE)(IMyInterface ** pInterface);
    
    	HRESULT FreeInterface( IMyInterface **pInterface );
    	typedef HRESULT (*FREEINTERFACE)(IMyInterface ** pInterface);
    }
    
    #endif
    This is the implementation of the above file:

    Code:
    #include <iostream>
    
    #define DLL_EXPORT
    
    #include "dllSrc.h"
    #include "dllClass.h"
    
    extern "C"
    {
    	HRESULT GetInterface( IMyInterface **pInterface )
    	{
    		if( !*pInterface )
    		{
    			*pInterface = new MyClass;
    			return S_OK;
    		}
    		return E_FAIL;
    	}
    
    	HRESULT FreeInterface( IMyInterface **pInterface )
    	{
    		if( !*pInterface )
    		{
    			return E_FAIL;
    		}
    
    		delete *pInterface;
    		*pInterface = 0;
    
    		return S_OK;
    	}
    }
    This is the class that the dll is supposed to give to the main app:

    Code:
    #ifndef __DLL_CLASS_H__
    #define __DLL_CLASS_H__
    #include <iostream>
    
    class MyClass : public IMyInterface
    {
    public:
    	MyClass();
    	~MyClass();
    
    	bool Init(int params);
    	bool Release();
    	bool DoStuff();
    };
    
    MyClass::MyClass(){ std::cout<<"MyClass()\n"; }
    MyClass::~MyClass(){ std::cout<<"~MyClass()\n"; }
    bool MyClass::Init(int params){ std::cout<<"Init("<<params<<")\n"; return true; }
    bool MyClass::Release(){ std::cout<<"Release()\n"; return true; }
    bool MyClass::DoStuff(){ std::cout<<"DoStuff()\n"; return true; }
    
    #endif
    and the def file:
    Code:
    LIBRARY	"myDLL"
    EXPORTS
    	GetInterface
    	FreeInterface
    When I compile it I get 26 errors... 25 of them are either undeclared identifier (GETINTERFACE and FREEINTERFACE or whatever was made using them) or errors like "left of ->Init must point to class/struct/generic type."

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, as some have pointed out, I think, you haven't actually included the file which contains the declaration for GETINTERFACE into the main app source file.
    So include "dllsrc.h" in your main file.
    And one other thing. Stay away from conio.h.
    Use cin.get() instead of _getch().
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    May 2008
    Posts
    3
    Ohh sorry about that, I hit ctrl z too many times and include got erased.. Adding the header makes it work exactly like I wanted it to..

    Thanks so much!!

    I'll look into _getch() vs cin as well.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Glad to hear it's working for you.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Loading a DLL that is not in the same directory as the executable
    By starcatcher in forum Windows Programming
    Replies: 10
    Last Post: 12-13-2008, 07:05 AM
  2. Loading Struct from dll
    By peyman_k in forum C++ Programming
    Replies: 2
    Last Post: 08-15-2008, 03:12 PM
  3. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  4. Loading a DLL at runtime
    By filler_bunny in forum Windows Programming
    Replies: 9
    Last Post: 02-23-2003, 08:03 AM