-
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.
-
You would have a header file that declares GETINTERFACE as extern, included by both the dll and the client, I think.
-
Including a header will not link your dll to your program, so including it will not do any harm.
-
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."
-
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().
-
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.
-
Glad to hear it's working for you.