Adding dll's to the project and making functions work - c++

I have to do one project and I was given dll and a header file with implemented functions needed for the project. I was told just to add the header file to the project but this way i get unresolve externals error if i try to use functions referenced in header. So what needs to be done to make everything work? Visual Studio 2010.
Here are the files i have: http://www.ipix.lt/images/33871682.png
And this is header file:
#ifndef __BIM482_RADAR__
#define __BIM482_RADAR__
int BIM482OpenRadar();
int BIM482AddPlane(double x, double y);
int BIM482SetPlaneColor(int planeidx, int coloridx);
int BIM482SetPlanePos(int planeidx, double x, double y);
void BIM482UpdateRadar();
#endif // __BIM482_RADAR__
I need to initiate gui with OpenRadar and pass information with those functions. How to start this thing?

You don't have a .lib-file to link against.
Maybe this can help you
http://www.coderetard.com/2009/01/21/generate-a-lib-from-a-dll-with-visual-studio/
or this:
http://support.microsoft.com/default.aspx?scid=kb;en-us;131313
or this:
http://www.asawicki.info/news_1420_generating_lib_file_for_dll_library.html
when you have generated the lib-file ,you must use __declspec(dllimport) on yuor functions in the header file.
An alternative to all of the above is to use LoadLibrary(...) in your source and write wrapper function for those function in the dll and call those dll funcions via GetProcAddress(...).
struct
{
HMODULE hDll;
int (*BIM482OpenRadar) ();
int (*BIM482AddPlane) (double x, double y);
int (*BIM482SetPlaneColor) (int planeidx, int coloridx);
int (*BIM482SetPlanePos) (int planeidx, double x, double y);
void (*BIM482UpdateRadar) ();
} dll_funcs = {0};
bool ExitRadar( LPCTSTR szDllPath )
{
if (dll_funcs.hDll)
FreeLibrary( dll_funcs.hDll );
return true;
}
bool InitRadar( LPCTSTR szDllPath )
{
if (dll_funcs.hDll)
return true;
dll_funcs.hDll = LoadLibrary( szDllPath );
if (!dll_funcs.hDll)
return false;
dll_funcs.BIM482OpenRadar = (int(*)())GetProcAddress( dll_funcs.hDll ,("BIM482OpenRadar") );
dll_funcs.BIM482AddPlane = (int(*)(double,double))GetProcAddress( dll_funcs.hDll ,("BIM482AddPlane") );
dll_funcs.BIM482SetPlaneColor = (int(*)(int,int))GetProcAddress( dll_funcs.hDll ,("BIM482SetPlaneColor") );
dll_funcs.BIM482SetPlanePos = (int(*)(int,double,double))GetProcAddress( dll_funcs.hDll ,("BIM482SetPlanePos") );
dll_funcs.BIM482UpdateRadar = (void(*)())GetProcAddress( dll_funcs.hDll ,("BIM482UpdateRadar") );
return true;
}
int BIM482OpenRadar ()
{ return (*dll_funcs.BIM482OpenRadar)(); };
int BIM482AddPlane (double x, double y)
{ return (*dll_funcs.BIM482AddPlane)( x ,y ); }
int BIM482SetPlaneColor (int planeidx, int coloridx )
{ return (*dll_funcs.BIM482SetPlaneColor)( planeidx ,coloridx ); }
int BIM482SetPlanePos (int planeidx, double x, double y)
{ return (*dll_funcs.BIM482SetPlanePos)( planeidx ,x ,y ); }
void BIM482UpdateRadar ()
{ return (*dll_funcs.BIM482UpdateRadar)(); }

There is a windows call that loads a DLL into your image. You can either add it to the compile setup in Visual Studio, or load it dynamically.
The easiest thing is probably to do it at compile time; google "Visual Studio llinking options".

You'll need to export the function from dll, while import the function from your exe. Like:
#if defined(XYZLIBRARY_EXPORT) // inside DLL
#define XYZAPI __declspec(dllexport)
#else // outside DLL
#define XYZAPI __declspec(dllimport)
#endif // XYZLIBRARY_EXPORT
int XYZAPI BIM482OpenRadar();
int XYZAPI BIM482AddPlane(double x, double y);
int XYZAPI BIM482SetPlaneColor(int planeidx, int coloridx);
int XYZAPI BIM482SetPlanePos(int planeidx, double x, double y);
void XYZAPI BIM482UpdateRadar();
In DLL, i suggest to add a macro, and add XYZLIBRARY_EXPORT in pre-processor
It will export all of your function.
In EXE, import the function, without adding pre-processor, as it will import the function by default.

In addition to including header files, you need to link your program with the corresponding libraries. From your screenshot, you seem to have .a files, which are indeed libraries, but unfortunately they are meant for use with the GCC toolchain and will not work with Visual Studio. You either need to get .lib files if you must use Visual Studio, or otherwise switch to a GCC port such as MinGW.

You may use windows API LoadLibrary to load the dll during runtime, followed by GetProcAddress to retrieve function address. With the function address is retrieved, you need to declare the method signature so that compiler know how to call given function.
Below is a sample code for how to "link" to function in Dll:
HINSTANCE m_hExtDll = LoadLibrary( "SDL.dll" )
if (m_hExtDll)
{
FARPROC m_pfnOpenRadar = GetProcAddress(m_hExtDll, "BIM482OpenRadar")
if (m_pfnOpenRadar)
{
typedef int (*OPENRADARFUNC)();
OPENRADARFUNC fnOpenRadar = (OPENRADARFUNC)m_pfnOpenRadar;
int iRetCode = fnOpenRadar();
}
}
Do note that functions exported are subject to name mangling and you can verify the function name using third-party utility like Dependency Walker.

Related

Visual studio 2013 express crashes when trying to debug C++ dll (x64) using excel

I am a beginner, and I just built a project including a dll in c++. The project is made up with 2 sub projects:
A static Library project containing the files:
Rational.h
#pragma once
class Rational
{
private:
int num;
int den;
public:
Rational(int num_, int den_);
Rational();
double getValue();
};
Rational.cpp
#include "Rational.h"
Rational::Rational()
{
}
Rational::Rational(int num_, int den_) : den(den_), num(num_)
{
}
double Rational::getValue()
{
return (double)num / (double) den;
}
A dll project containing the files:
Proxy.h
#pragma once
#define DLL_EXPORT __declspec(dllexport)
extern "C"
{
DLL_EXPORT double __stdcall getRationalValue(int num_, int den_);
}
Proxy.cpp
#include "Proxy.h"
#include "Rational.h"
DLL_EXPORT double __stdcall getRationalValue(int num_, int den_)
{
Rational fraction(num_, den_);
return fraction.getValue();
}
The dll function is used in an Excel file. Here is the declaration of the function to be used:
Declare PtrSafe Function getRationalValue_vba Lib "C:\...\Documents\Visual Studio 2013\Projects\Rational\x64\Debug\RationalDll.dll" Alias "getRationalValue" (ByVal num As Long, ByVal den As Long) As Double
In order to test this function I have the following sub in vba:
Sub test()
shtTests.Cells(1, 1) = getRationalValue_vba(4, 5)
End Sub
It seems to work fine.
The problem occurs when I want to launch the debugger from Visual Studio.
In visual studio project:
Properties>Debugging>Command was set to Excel.exe localisation.
I set a break point at the "return" line of proxy.cpp file.
When I launch the debugger, excel opens well. But then, when I execute sub test(), the break point in visual is never reached, and the application crashes.
Can you help me understand this issue?

How do I call a function from my DLL during run-time linking?

I do not understand DLLs very well, so I've constructed a simple example that I woudl like some help with. I have a simple dll here.
// HelloDLL.cpp
#include "stdafx.h"
int __declspec(dllexport) Hello(int x, int y);
int Hello(int x, int y)
{
return (x + y);
}
How would I call the Hello(int x, int y) function in a separate program once I've run LoadLibrary()? Here's a rough layout of what I have so far but I'm not sure if what I have is correct, and if it is, how to proceed.
// UsingHelloDLL.cpp
#include "stdafx.h"
#include <windows.h>
int main(void)
{
HINSTANCE hinstLib;
// Get the dll
hinstLib = LoadLibrary(TEXT("HelloDLL.dll"));
// If we got the dll, then get the function
if (hinstLib != NULL)
{
//
// code to handle function call goes here.
//
// Free the dll when we're done
FreeLibrary(hinstLib);
}
// else print a message saying we weren't able to get the dll
printf("Could not load HelloDLL.dll\n");
return 0;
}
Could anyone help me out on how to handle the function call? Any special cases I should be aware of for future usage of dlls?
After loading the library, what you need is to find the function pointer. The function Microsoft provides is GetProcAdderess. Unfortuantely, you have to know function prototype. If you don't knwo, we are going all the way to COM/DCOM, etc. Probably out of your scope.
FARPROC WINAPI GetProcAddress( _In_ HMODULE hModule, _In_ LPCSTR lpProcName );
So in your example, what you do nromally is like this:
typedef int (*THelloFunc)(int,int); //This define the function prototype
if (hinstLib != NULL)
{
//
// code to handle function call goes here.
//
THelloFunc f = (THelloFunc)GetProcAddress(hinstLib ,"Hello");
if (f != NULL )
f(1, 2);
// Free the dll when we're done
FreeLibrary(hinstLib);
}

using C++ 2010 dll in excel

Ive built a simple dll in c++ using Visual C++ 2010 and am trying to use it in excel. The project name is "SwapFunDLL", the source files name is "swapmain" and the name of the header file containing the class and its function is "DateNTime". Ive attached them below. The code takes in two values and then uses the class function to multiply them and then returns the product (i realize the class and function arent necessary, im just doing this to learn). The function compiles with not errors however when the function is used in excel i get a value error. Could someone please help me see what im doing wrong thanks.
header:
// DateNTime.h
//Avoid need of .Def file
#ifdef SwapFunDLL_EXPORTS
#define SwapFunDLL_API __declspec(dllexport)
#else
#define SwapFunDLL_API __declspec(dllimport)
#endif
namespace DateNTime
{
class SwapFunDLL_API Date
{
double x,y;
public:
double datediff(double,double);
};
double Date::datediff(double x, double y)
{
return x*y;
}
}
Source File:
#include "DateNTime.h"
namespace DateNTime
{
double returndates(double a, double b)
{
Date Date;
return Date.datediff(a,b);
}
}
Excel Macro:
Declare Function SwapFunDLL _
Lib "C:\Users\MIKE\Desktop\c++ tial programs\SwapFunDLL\Debug\SwapFunDLL.dll" _
(ByRef x As Double, ByRef y As Double) As Double
your import declaration is wrong. Two things: the semantics and declaration of types. If you use pointers than in Excel you say ByRef, but if you use by value passing you say ByVal.
Declare this function as:
Declare Function returndates Lib "C:\Users\MIKE\Desktop\c++ tial programs\SwapFunDLL\Debug\SwapFunDLL.dll" _ (ByVal x As Double, ByVal y As Double) As Double
make your function returndates member of your class that is being exported, static member.
also make your function static and in any case you can declare this export in .def file (just simply: "returdates" it's all). After all of it this has to work unless your C++ code is OK.
also here:
double returndates(double a, double b)
{
Date Date; //<- change it, i.e: Date d; d.datediff(); does it compile?
return Date.datediff(a,b);
}
you can change the code just to test if you do everything correctly to such "test info" form:
double returndates(double a, double b)
{
return 117;
}
and try it in Excel.
Excel needs __stdcall, so make a functions declarations inside your class like this:
static double __stdcall returndates(double a, double b);
then define it in .cpp file as:
SwapFunDLL_API double __stdcall DateNTime::Date::returndtes(double a, double b){
return 117;
}
after all these changes should be OK.

Problems creating a unmanaged regular MFC DLL and call it from an managed C++ .NET app

I have a few questions about DLL's. I tried a lot but I can not get the complete picture. Most examples are in C# etc.
With the wizard in VS2005 I created a unmanaged MFC regular DLL (must be MFC because of remaining code). Then I tried to import it in a VS2005 managed .NET C++ application. See code below.
mfc_main.h:
//---------------------------------------------------------
// mfc_main.h : main header file for the mfc_main DLL
//---------------------------------------------------------
#pragma once
#ifndef __AFXWIN_H__
#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
class __declspec(dllexport) Cmfc_mainApp : public CWinApp
{
public:
Cmfc_mainApp();
// Overrides
public:
virtual BOOL InitInstance();
int SayHello(int j);
int init;
DECLARE_MESSAGE_MAP()
};
mfc_main.cpp:
//----------------------------------------------------------------
// mfc_main.cpp : Defines the initialization routines for the DLL.
//----------------------------------------------------------------
#include "stdafx.h"
#include "mfc_main.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
BEGIN_MESSAGE_MAP(Cmfc_mainApp, CWinApp)
END_MESSAGE_MAP()
Cmfc_mainApp::Cmfc_mainApp()
{
}
Cmfc_mainApp theApp;
BOOL Cmfc_mainApp::InitInstance()
{
CWinApp::InitInstance();
return TRUE;
}
int Cmfc_mainApp::SayHello(int j)
{
init = 12; // Comment this out the application works !!!!
return j * 6;
};
in application
[DllImport("mfc_main.dll",
EntryPoint = "?SayHello#Cmfc_mainApp##QAEHH#Z",
ExactSpelling = true)]
static int SayHello(int a);
......
private: System::Void button_Click(System::Object^ sender, System::EventArgs^ e)
{
int retval = SayHello(2);
}
My questions are:
1 - Why is it working without the init = 12 in the function SayHello and with the application crashes (error: Attempted to read or write protected memory)?
2 - Is in this case the InitInstance() executed although I don't call it (and why is there no ExitInstance)?
3 - Why do I see some examples giving the EntryPoint when using DLLImport and some don't?
4 - Can I give a delegate as parameter to a function in a MFC C++ DLL instead of a normal function pointer, to create a callback?
Methods cannot be P/Invoked. If you want to export a class from unmanaged DLL to be used in managed world, you have to flatten it, eg.
Create a constructor function, which looks like:
__declspec(dllexport) void * __stdcall MyClass_Create()
{
return new MyClass();
}
Create a destructor function, which looks like:
__declspec(dllexport) void * __stdcall MyClass_Destroy(MyClass * instance)
{
delete instance;
}
Flatten method calls. Let's suppose, that you have the following method in your class:
int MyClass::MyMethod(int i, double j) { ... }
Then you have to create a following function:
__declspec(dllexport) int __stdcall MyClass_MyMethod(MyClass * instance, int i, double j)
{
return instance->MyMethod(i, j);
}
Prepare P/Invoked external methods in C# (You already know how to do it, so I'll omit these)
Create instance of your class:
IntPtr instance = MyClass_Create();
Then call its method:
int i = MyClass_MyMethod(instance, 4, 2.0);
Finally, destroy the class:
MyClass_Destroy(instance);
Don't forget to add some error checking - I omitted it to keep the example clear.

Dynamically load a function from a DLL

I'm having a little look at .dll files, I understand their usage and I'm trying to understand how to use them.
I have created a .dll file that contains a function that returns an integer named funci()
using this code, I (think) I've imported the .dll file into the project(there's no complaints):
#include <windows.h>
#include <iostream>
int main() {
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents and Settings\\User\\Desktop \\fgfdg\\dgdg\\test.dll");
if (hGetProcIDDLL == NULL) {
std::cout << "cannot locate the .dll file" << std::endl;
} else {
std::cout << "it has been called" << std::endl;
return -1;
}
int a = funci();
return a;
}
# funci function
int funci() {
return 40;
}
However when I try to compile this .cpp file that I think has imported the .dll I have the following error:
C:\Documents and Settings\User\Desktop\fgfdg\onemore.cpp||In function 'int main()':|
C:\Documents and Settings\User\Desktop\fgfdg\onemore.cpp|16|error: 'funci' was not declared in this scope|
||=== Build finished: 1 errors, 0 warnings ===|
I know a .dll is different from a header file so I know I can't import a function like this but it's the best I could come up with to show that I've tried.
My question is, how can I use the hGetProcIDDLL pointer to access the function within the .dll.
I hope this question makes sense and I'm not barking up some wrong tree yet again.
LoadLibrary does not do what you think it does. It loads the DLL into the memory of the current process, but it does not magically import functions defined in it! This wouldn't be possible, as function calls are resolved by the linker at compile time while LoadLibrary is called at runtime (remember that C++ is a statically typed language).
You need a separate WinAPI function to get the address of dynamically loaded functions: GetProcAddress.
Example
#include <windows.h>
#include <iostream>
/* Define a function pointer for our imported
* function.
* This reads as "introduce the new type f_funci as the type:
* pointer to a function returning an int and
* taking no arguments.
*
* Make sure to use matching calling convention (__cdecl, __stdcall, ...)
* with the exported function. __stdcall is the convention used by the WinAPI
*/
typedef int (__stdcall *f_funci)();
int main()
{
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents and Settings\\User\\Desktop\\test.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
// resolve function address here
f_funci funci = (f_funci)GetProcAddress(hGetProcIDDLL, "funci");
if (!funci) {
std::cout << "could not locate the function" << std::endl;
return EXIT_FAILURE;
}
std::cout << "funci() returned " << funci() << std::endl;
return EXIT_SUCCESS;
}
Also, you should export your function from the DLL correctly. This can be done like this:
int __declspec(dllexport) __stdcall funci() {
// ...
}
As Lundin notes, it's good practice to free the handle to the library if you don't need them it longer. This will cause it to get unloaded if no other process still holds a handle to the same DLL.
In addition to the already posted answer, I thought I should share a handy trick I use to load all the DLL functions into the program through function pointers, without writing a separate GetProcAddress call for each and every function. I also like to call the functions directly as attempted in the OP.
Start by defining a generic function pointer type:
typedef int (__stdcall* func_ptr_t)();
What types that are used aren't really important. Now create an array of that type, which corresponds to the amount of functions you have in the DLL:
func_ptr_t func_ptr [DLL_FUNCTIONS_N];
In this array we can store the actual function pointers that point into the DLL memory space.
Next problem is that GetProcAddress expects the function names as strings. So create a similar array consisting of the function names in the DLL:
const char* DLL_FUNCTION_NAMES [DLL_FUNCTIONS_N] =
{
"dll_add",
"dll_subtract",
"dll_do_stuff",
...
};
Now we can easily call GetProcAddress() in a loop and store each function inside that array:
for(int i=0; i<DLL_FUNCTIONS_N; i++)
{
func_ptr[i] = GetProcAddress(hinst_mydll, DLL_FUNCTION_NAMES[i]);
if(func_ptr[i] == NULL)
{
// error handling, most likely you have to terminate the program here
}
}
If the loop was successful, the only problem we have now is calling the functions. The function pointer typedef from earlier isn't helpful, because each function will have its own signature. This can be solved by creating a struct with all the function types:
typedef struct
{
int (__stdcall* dll_add_ptr)(int, int);
int (__stdcall* dll_subtract_ptr)(int, int);
void (__stdcall* dll_do_stuff_ptr)(something);
...
} functions_struct;
And finally, to connect these to the array from before, create a union:
typedef union
{
functions_struct by_type;
func_ptr_t func_ptr [DLL_FUNCTIONS_N];
} functions_union;
Now you can load all the functions from the DLL with the convenient loop, but call them through the by_type union member.
But of course, it is a bit burdensome to type out something like
functions.by_type.dll_add_ptr(1, 1); whenever you want to call a function.
As it turns out, this is the reason why I added the "ptr" postfix to the names: I wanted to keep them different from the actual function names. We can now smooth out the icky struct syntax and get the desired names, by using some macros:
#define dll_add (functions.by_type.dll_add_ptr)
#define dll_subtract (functions.by_type.dll_subtract_ptr)
#define dll_do_stuff (functions.by_type.dll_do_stuff_ptr)
And voilĂ , you can now use the function names, with the correct type and parameters, as if they were statically linked to your project:
int result = dll_add(1, 1);
Disclaimer: Strictly speaking, conversions between different function pointers are not defined by the C standard and not safe. So formally, what I'm doing here is undefined behavior. However, in the Windows world, function pointers are always of the same size no matter their type and the conversions between them are predictable on any version of Windows I've used.
Also, there might in theory be padding inserted in the union/struct, which would cause everything to fail. However, pointers happen to be of the same size as the alignment requirement in Windows. A static_assert to ensure that the struct/union has no padding might be in order still.
This is not exactly a hot topic, but I have a factory class that allows a dll to create an instance and return it as a DLL. It is what I came looking for but couldn't find exactly.
It is called like,
IHTTP_Server *server = SN::SN_Factory<IHTTP_Server>::CreateObject();
IHTTP_Server *server2 =
SN::SN_Factory<IHTTP_Server>::CreateObject(IHTTP_Server_special_entry);
where IHTTP_Server is the pure virtual interface for a class created either in another DLL, or the same one.
DEFINE_INTERFACE is used to give a class id an interface. Place inside interface;
An interface class looks like,
class IMyInterface
{
DEFINE_INTERFACE(IMyInterface);
public:
virtual ~IMyInterface() {};
virtual void MyMethod1() = 0;
...
};
The header file is like this
#if !defined(SN_FACTORY_H_INCLUDED)
#define SN_FACTORY_H_INCLUDED
#pragma once
The libraries are listed in this macro definition. One line per library/executable. It would be cool if we could call into another executable.
#define SN_APPLY_LIBRARIES(L, A) \
L(A, sn, "sn.dll") \
L(A, http_server_lib, "http_server_lib.dll") \
L(A, http_server, "")
Then for each dll/exe you define a macro and list its implementations. Def means that it is the default implementation for the interface. If it is not the default, you give a name for the interface used to identify it. Ie, special, and the name will be IHTTP_Server_special_entry.
#define SN_APPLY_ENTRYPOINTS_sn(M) \
M(IHTTP_Handler, SNI::SNI_HTTP_Handler, sn, def) \
M(IHTTP_Handler, SNI::SNI_HTTP_Handler, sn, special)
#define SN_APPLY_ENTRYPOINTS_http_server_lib(M) \
M(IHTTP_Server, HTTP::server::server, http_server_lib, def)
#define SN_APPLY_ENTRYPOINTS_http_server(M)
With the libraries all setup, the header file uses the macro definitions to define the needful.
#define APPLY_ENTRY(A, N, L) \
SN_APPLY_ENTRYPOINTS_##N(A)
#define DEFINE_INTERFACE(I) \
public: \
static const long Id = SN::I##_def_entry; \
private:
namespace SN
{
#define DEFINE_LIBRARY_ENUM(A, N, L) \
N##_library,
This creates an enum for the libraries.
enum LibraryValues
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_ENUM, "")
LastLibrary
};
#define DEFINE_ENTRY_ENUM(I, C, L, D) \
I##_##D##_entry,
This creates an enum for interface implementations.
enum EntryValues
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_ENUM)
LastEntry
};
long CallEntryPoint(long id, long interfaceId);
This defines the factory class. Not much to it here.
template <class I>
class SN_Factory
{
public:
SN_Factory()
{
}
static I *CreateObject(long id = I::Id )
{
return (I *)CallEntryPoint(id, I::Id);
}
};
}
#endif //SN_FACTORY_H_INCLUDED
Then the CPP is,
#include "sn_factory.h"
#include <windows.h>
Create the external entry point. You can check that it exists using depends.exe.
extern "C"
{
__declspec(dllexport) long entrypoint(long id)
{
#define CREATE_OBJECT(I, C, L, D) \
case SN::I##_##D##_entry: return (int) new C();
switch (id)
{
SN_APPLY_CURRENT_LIBRARY(APPLY_ENTRY, CREATE_OBJECT)
case -1:
default:
return 0;
}
}
}
The macros set up all the data needed.
namespace SN
{
bool loaded = false;
char * libraryPathArray[SN::LastLibrary];
#define DEFINE_LIBRARY_PATH(A, N, L) \
libraryPathArray[N##_library] = L;
static void LoadLibraryPaths()
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_PATH, "")
}
typedef long(*f_entrypoint)(long id);
f_entrypoint libraryFunctionArray[LastLibrary - 1];
void InitlibraryFunctionArray()
{
for (long j = 0; j < LastLibrary; j++)
{
libraryFunctionArray[j] = 0;
}
#define DEFAULT_LIBRARY_ENTRY(A, N, L) \
libraryFunctionArray[N##_library] = &entrypoint;
SN_APPLY_CURRENT_LIBRARY(DEFAULT_LIBRARY_ENTRY, "")
}
enum SN::LibraryValues libraryForEntryPointArray[SN::LastEntry];
#define DEFINE_ENTRY_POINT_LIBRARY(I, C, L, D) \
libraryForEntryPointArray[I##_##D##_entry] = L##_library;
void LoadLibraryForEntryPointArray()
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_POINT_LIBRARY)
}
enum SN::EntryValues defaultEntryArray[SN::LastEntry];
#define DEFINE_ENTRY_DEFAULT(I, C, L, D) \
defaultEntryArray[I##_##D##_entry] = I##_def_entry;
void LoadDefaultEntries()
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_DEFAULT)
}
void Initialize()
{
if (!loaded)
{
loaded = true;
LoadLibraryPaths();
InitlibraryFunctionArray();
LoadLibraryForEntryPointArray();
LoadDefaultEntries();
}
}
long CallEntryPoint(long id, long interfaceId)
{
Initialize();
// assert(defaultEntryArray[id] == interfaceId, "Request to create an object for the wrong interface.")
enum SN::LibraryValues l = libraryForEntryPointArray[id];
f_entrypoint f = libraryFunctionArray[l];
if (!f)
{
HINSTANCE hGetProcIDDLL = LoadLibraryA(libraryPathArray[l]);
if (!hGetProcIDDLL) {
return NULL;
}
// resolve function address here
f = (f_entrypoint)GetProcAddress(hGetProcIDDLL, "entrypoint");
if (!f) {
return NULL;
}
libraryFunctionArray[l] = f;
}
return f(id);
}
}
Each library includes this "cpp" with a stub cpp for each library/executable. Any specific compiled header stuff.
#include "sn_pch.h"
Setup this library.
#define SN_APPLY_CURRENT_LIBRARY(L, A) \
L(A, sn, "sn.dll")
An include for the main cpp. I guess this cpp could be a .h. But there are different ways you could do this. This approach worked for me.
#include "../inc/sn_factory.cpp"