C++ Library Cross-Calling - c++

I'm not really sure if that is the actual name of what I mean, but you'll get it.
Supose I have 3 projects, 2 of them builds as libraries, and the other one as an executable. For my scenario I'll use MSVC++ and the libraries will be dynamic (DLLs), and of course executable .exe, but I also want to if static libraries are also included.
And please, if I'm wrong on any of my assumptions, please correct me.
In the first library project, FirstLib.h:
#pragma once
#include <SecondLib.h>
#ifdef DLLONE_BUILD
#define DLLONE_API __declspec(dllexport)
#else
#define DLLONE_API __declspec(dllimport)
#endif
int DLLONE_API MainOne();
int DLLONE_API InternalOne();
and FirstLib.cpp:
#include <FirstLib.h>
int MainOne() { return InternalTwo(); }
int InternalOne() { return 100; }
Similarly, in the first project, SecondLib.h:
#pragma once
#include <FirstLib.h>
#ifdef DLLTWO_BUILD
#define DLLTWO_API __declspec(dllexport)
#else
#define DLLTWO_API __declspec(dllimport)
#endif
int DLLTWO_API MainTwo();
int DLLTWO_API InternalTwo();
SecondLib.cpp:
#include <SecondLib.h>
int MainTwo() { return InternalOne(); }
int InternalTwo() { return 200; }
Finally, in the executable project, main.cpp:
#include <FirstLib.h>
#include <SecondLib.h>
int main() { return MainOne() + MainTwo(); }
So when compiling the two libraries, I obtain the two .dll files, and two .lib files. Each library must have the other library .lib to link.
Then, the executable must be linked with the two .lib, and when executed, .dll should be in a known path for the exe, be the same path or some PATH.
Now for the questions:
Is doing this a correct aproach, or should be avoided?
Exe needs the two dlls, but each dll needs the other dll. Does each dll loads the other one again, or uses the same loaded version from .exe?
If they were static libraries, would each library be loaded two times, or just one? Or none of them?
And if you have a good resource where I can find more about this, it will be really apreciated.
Thanks in advance!
UPDATE as why would I do this : Imagine creating an engine.
I have (just to be consistent with the previous scenario) a library called Kernel, and a library called System. Also a binary project.
Kernel has the code regarding program execution (main loop), handling, base clases and other high level things.
System has the code regarding HAL and low level code. OpenGL things, file IO things, etc.
Binary has the main function, and program specific implementation of the engine.
Why do I need that cross-linking:
Kernel in Binary: main() (Binary) calls Kernel.Initialize() (Kernel).
System in Binary: CreateActor()(Binary) calls System.OpenGl.MeshCreate() (System)
System in Kernel: Kernel.Initialize()(Kernel) Initializes the Kernel, but also the System by calling System.Initialize()(System).
Kernel in System: class System(System) inherits from class Object(Kernel)
I know i could avoid this circular dependency by, say, Initializing System from binary calling System.Initialize()after Kernel.Initialize().
But then, Kernel will depend on no one, System would depend on Kernel, and Binary on both Kernel and System.
So my question remains in this case too
Is removing the cross dependency but to have this scheme a better aproach?
Same as question two: Does Binary and System both depending on Kernel as well asBinary in System represents double code, double loading or a performance or size downgrade or some kind of undesirable effect?

Related

Static library able to link with any other object, regardless of C++ runtime used by that object

I am trying to determine if it is possible at all to create a static library that:
Internally uses Microsoft/STL, static release runtime (/MT)
Can be linked to objects not using /MT (e.g., Dynamic DLL Release, Static Debug, etc.)
The specific test code I'm trying to get working is as follows:
Header:
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int EncapLibConcatenate(int a, int b);
#ifdef __cplusplus
}
#endif
Source:
#include "EncapLib.h"
#include <string>
int EncapLibConcatenate(int a, int b)
{
try {
return std::stoi(std::to_string(a) + std::to_string(b));
} catch (...) {
return 0;
}
}
Linking to the above predictably results in a /FAILIFMISMATCH error when not using /MT for the project that links to the above library. I would like to learn of any compiler / linker options to circumvent this issue. If such do not exist, then any other approaches (such as modifying the .obj COFF files post-build) would also be welcome.
As a side note, I am aware that creating a dynamic library is the idiomatic approach to encapsulating library dependencies; this is a question regarding technical possibilities, not best practices. I have also been able to create a runtime-agnostic static library by eschewing any use of the standard library (restricting to C runtime and win32). This question is specifically about a static library that uses the C++ standard library internally (though pointedly not at its interface).

How do is structure my files right, when I write code for linux and windows

I am currently not sure how I should seperate my code best. I currently programming a software which should run on Linux and Windows. So I decided to put all OS-secificstuff in thier own folder/files.
For example
This is the header file:
#ifdef __linux__
#include <unistd.h>
#elif _WIN64
#include <Windows.h>
#endif
#include <string>
#include <iostream>
#pragma once
class SystemTools
{
public:
// Delay in secounds until the programm continues
static void sleep(int delay);
private:
};
and the OS specific implementation is in the linux/windows folder
Linux:
#ifdef __linux__
#include "../SystemTools.h"
void SystemTools::sleep(int delay)
{
usleep(delay*1000000);
}
#endif
Windows:
#ifdef _WIN64
#include "../SystemTools.h"
void SystemTools::sleep(int delay)
{
Sleep(delay*1000);
}
#endif
This works and I have no problems so far, but when I now have methods which don´t need any OS specific code I created an additional folder "Generic" so I can write the code in there and don´t have to mantain the same code in the linux and windows file. For example like that:
Generic:
#include "../SystemTools.h"
void SystemTools::sleepMin(int delay)
{
sleep(delay*60);
}
#endif
That still workes on Linux but not on Windows (no error but does not compile, used codeblockes for that on windows). So how do I organize my code correct? Should I use only one file with ifdef even it that gets very fast ugly?
(compiler Linux: g++, Windows: should be MinGW)
Firstly I'd suggest you to use the most recent of C++ (C++20 or so) on your project. This way, we can abstract many OS related calls (like threading, synchronization, random numbers and etc).
That means, you won't really need to use too many of OS specific APIs. IE: C++11 and earlier already have a standard way to sleep:
https://en.cppreference.com/w/cpp/thread/sleep_for
In the end, if you really need to call OS specific things on windows and on linux, using a library could be interesting and pay attention that windows C++ compiler (visual studio) really like to use 'pre compiled headers' so, it's interesting to have a single header file where all windows specific headers can be included.
Basically that. You can have a standard Cmake or makefile for your linux build and use .sln Visual Studio project to build it to windows.
That's the way I would do that

Exporting constants from a DLL

I'm working with VC9 on Windows.
I have a library (lets call it libfoo) which is made of the following files ("include guards" and "#include" directives omited for clarity's sake):
// foo.hpp
class Foo
{
public:
static const std::string SOME_CONST;
};
And:
// foo.cpp
#include "foo.hpp"
const std::string Foo::SOME_CONST = "hello";
Foo::SOME_CONST is exported using a .def file.
The library compiles fine: a libfoo.lib file and a libfoo.dll file are generated.
I used this library in a sample program, like:
// main.cpp
#include <foo.hpp>
int main()
{
std::cout << Foo::SOME_CONST << std::endl; // std::bad_alloc here
return EXIT_SUCCESS;
}
A std::bad_alloc is thrown whenever I attempt to use Foo::SOME_CONST.
This only happens if I link dynamically to libfoo. Linking statically results in a perfectly working program.
What could possibly be going on here ? Is it legal to export a std::string constant that way ?
Check if dll actually does dynamic initialization, because it might not, standard has no requirements for dynamic libraries. Wrapping globals in static functions can be the solution.
Use __declspec(dllexport) and __declspec(dllimport). Stop worrying about .def files and all of that rubbish- let the compiler do the work.
Are the library and the main application linking to the same version of the standard library and/or CRT and/or MFC, with exactly the same settings? I've seen allocation issues when using different versions of the CRT, and also fought bugs caused by different iterator debugging settings between a library and its including application.

Multiple application entry points

Recently I was trying to add unit tests to an existing binary by creating a extra (DLLMain) entry point to an application that already has a main entry point (it is a console exe). The application seemed to compile correctly although I was unable to use it as a DLL from my python unit test framework, all attempts to use the exe as a dll failed.
Has anyone any ideas or experience in adding extra application entry point with any input as to why this would or wouldn't work?
There are some problems which you should solve to implement what you want:
The exe must have relocation table (use linker switch /FIXED:NO)
The exe must exports at least one function - it's clear how to do this.
I recommend use DUMPBIN.EXE with no some switches (/headers, /exports and without switches) to examine the exe headers. You can compare the structure of your application with Winword.exe or outlook.exe which exports some functions.
If all this will not helps, I'll try to write a test EXE application which can be loaded as an exe and post the code here.
UPDATED: Just now verified my suggestion. It works. File Loadable.c looks like following
#include <windows.h>
#include <stdio.h>
EXTERN_C int __declspec(dllexport) WINAPI Sum (int x, int y);
EXTERN_C int __declspec(dllexport) WINAPI Sum (int x, int y)
{
return x + y;
}
int main()
{
printf ("2+3=%d\n", Sum(2,3));
}
The only important linker switch is /FIXED:NO which one can find in advanced part of linker settings. The program can run and produced the output "2+3=5".
Another EXE loaded the EXE as a DLL and calls Sum function:
#include <windows.h>
#include <stdio.h>
typedef int (WINAPI *PFN_SUM) (int x, int y);
int main()
{
HMODULE hModule = LoadLibrary (TEXT("C:\\Oleg\\ExeAsDll\\Loadable.exe"));
PFN_SUM fnSum = (PFN_SUM) GetProcAddress (hModule, "_Sum#8");
int res = fnSum (5,4);
printf ("5+4=%d\n", res);
return 0;
}
The program also can run and produced the output "5+4=9".
I don't know for sure, but I would guess that Windows simply refuses to load an EXE in-process and a DLL as a new process, plain and simple.
These questions appear to contain more detail:
Can the DllMain of an .exe be called?
DllMain in an exe?
The simplest way to get both behaviours in one executable image is to design it as a DLL, then use rundll32.exe to execute it standalone. There's no need to write your own wrapper.

Compile a DLL in C/C++, then call it from another program

I want to make a simple, simple DLL which exports one or two functions, then try to call it from another program... Everywhere I've looked so far, is for complicated matters, different ways of linking things together, weird problems that I haven't even begun to realize exist yet... I just want to get started, by doing something like so:
Make a DLL which exports some functions, like,
int add2(int num){
return num + 2;
}
int mult(int num1, int num2){
int product;
product = num1 * num2;
return product;
}
I'm compiling with MinGW, I'd like to do this in C, but if there's any real differences doing it in C++, I'd like to know those also. I want to know how to load that DLL into another C (and C++) program, and then call those functions from it.
My goal here, after playing around with DLLs for a bit, is to make a VB front-end for C(++) code, by loading DLLs into visual basic (I have visual studio 6, I just want to make some forms and events for the objects on those forms, which call the DLL).
I need to know how to call gcc (/g++) to make it create a DLL, but also how to write (/generate) an exports file... and what I can/cannot do in a DLL (like, can I take arguments by pointer/reference from the VB front-end? Can the DLL call a theoretical function in the front-end? Or have a function take a "function pointer" (I don't even know if that's possible) from VB and call it?) I'm fairly certain I can't pass a variant to the DLL...but that's all I know really.
update again
Okay, I figured out how to compile it with gcc, to make the dll I ran
gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--out-implib,libmessage.a
and then I had another program load it and test the functions, and it worked great,
thanks so much for the advice,
but I tried loading it with VB6, like this
Public Declare Function add2 Lib "C:\c\dll\mydll.dll" (num As Integer) As Integer
then I just called add2(text1.text) from a form, but it gave me a runtime error:
"Can't find DLL entry point add2 in C:\c\dll\mydll.dll"
this is the code I compiled for the DLL:
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
EXPORT int __stdcall add2(int num){
return num + 2;
}
EXPORT int __stdcall mul(int num1, int num2){
return num1 * num2;
}
calling it from the C program like this worked, though:
#include<stdio.h>
#include<windows.h>
int main(){
HANDLE ldll;
int (*add2)(int);
int (*mul)(int,int);
ldll = LoadLibrary("mydll.dll");
if(ldll>(void*)HINSTANCE_ERROR){
add2 = GetProcAddress(ldll, "add2");
mul = GetProcAddress(ldll, "mul");
printf("add2(3): %d\nmul(4,5): %d", add2(3), mul(4,5));
} else {
printf("ERROR.");
}
}
any ideas?
solved it
To solve the previous problem, I just had to compile it like so:
gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--add-stdcall-alias
and use this API call in VB6
Public Declare Function add2 Lib "C:\c\dll\mydll" _
(ByVal num As Integer) As Integer
I learned not to forget to specify ByVal or ByRef explicitly--I was just getting back the address of the argument I passed, it looked like, -3048.
Regarding building a DLL using MinGW, here are some very brief instructions.
First, you need to mark your functions for export, so they can be used by callers of the DLL. To do this, modify them so they look like (for example)
__declspec( dllexport ) int add2(int num){
return num + 2;
}
then, assuming your functions are in a file called funcs.c, you can compile them:
gcc -shared -o mylib.dll funcs.c
The -shared flag tells gcc to create a DLL.
To check if the DLL has actually exported the functions, get hold of the free Dependency Walker tool and use it to examine the DLL.
For a free IDE which will automate all the flags etc. needed to build DLLs, take a look at the excellent Code::Blocks, which works very well with MinGW.
Edit: For more details on this subject, see the article Creating a MinGW DLL for Use with Visual Basic on the MinGW Wiki.
Here is how you do it:
In .h
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
extern "C" // Only if you are using C++ rather than C
{
EXPORT int __stdcall add2(int num);
EXPORT int __stdcall mult(int num1, int num2);
}
in .cpp
extern "C" // Only if you are using C++ rather than C
{
EXPORT int __stdcall add2(int num)
{
return num + 2;
}
EXPORT int __stdcall mult(int num1, int num2)
{
int product;
product = num1 * num2;
return product;
}
}
The macro tells your module (i.e your .cpp files) that they are providing the dll stuff to the outside world. People who incude your .h file want to import the same functions, so they sell EXPORT as telling the linker to import. You need to add BUILD_DLL to the project compile options, and you might want to rename it to something obviously specific to your project (in case a dll uses your dll).
You might also need to create a .def file to rename the functions and de-obfuscate the names (C/C++ mangles those names). This blog entry might be an interesting launching off point about that.
Loading your own custom dlls is just like loading system dlls. Just ensure that the DLL is on your system path. C:\windows\ or the working dir of your application are an easy place to put your dll.
There is but one difference. You have to take care or name mangling win C++. But on windows you have to take care about
1) decrating the functions to be exported from the DLL
2) write a so called .def file which lists all the exported symbols.
In Windows while compiling a DLL have have to use
__declspec(dllexport)
but while using it you have to write
__declspec(dllimport)
So the usual way of doing that is something like
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
The naming is a bit confusing, because it is often named EXPORT.. But that's what you'll find in most of the headers somwhere. So in your case you'd write (with the above #define)
int DLL_EXPORT add....
int DLL_EXPORT mult...
Remember that you have to add the Preprocessor directive BUILD_DLL during building the shared library.
Regards
Friedrich
The thing to watch out for when writing C++ dlls is name mangling. If you want interoperability between C and C++, you'd be better off by exporting non-mangled C-style functions from within the dll.
You have two options to use a dll
Either use a lib file to link the symbols -- compile time dynamic linking
Use LoadLibrary() or some suitable function to load the library, retrieve a function pointer (GetProcAddress) and call it -- runtime dynamic linking
Exporting classes will not work if you follow the second method though.
For VB6:
You need to declare your C functions as __stdcall, otherwise you get "invalid calling convention" type errors. About other your questions:
can I take arguments by pointer/reference from the VB front-end?
Yes, use ByRef/ByVal modifiers.
Can the DLL call a theoretical function in the front-end?
Yes, use AddressOf statement. You need to pass function pointer to dll before.
Or have a function take a "function pointer" (I don't even know if that's possible) from VB and call it?)
Yes, use AddressOf statement.
update (more questions appeared :)):
to load it into VB, do I just do the usual method (what I would do to load winsock.ocx or some other runtime, but find my DLL instead) or do I put an API call into a module?
You need to decaler API function in VB6 code, like next:
Private Declare Function SHGetSpecialFolderLocation Lib "shell32" _
(ByVal hwndOwner As Long, _
ByVal nFolder As Long, _
ByRef pidl As Long) As Long