Automatic initialization routine in C++ library? - c++

If i have a header file foo.h and a source file foo.cpp, and foo.cpp contains something along the lines of:
#ifdef WIN32
class asdf {
asdf() { startup_code(); }
~asdf() { cleanup_code(); }
};
asdf __STARTUP_HANDLE__
#else
//unix does not require startup or cleanup code in this case
#endif
but foo.h does not define class asdf, say i have an application bar.cpp:
#include "foo.h"
//link in foo.lib, foo.dll, foo.so, etc
int main() {
//do stuff
return 0;
}
If bar.cpp is compiled on a WIN32 platform, will the asdf() and ~asdf() be called at the appropriate times (before main() and at program exit, respectively) even though class asdf is not defined in foo.h, but is linked in through foo.cpp?

Yes -- but be very careful. The order in which static objects (like your asdf object) are initialized is undefined. So it is undefined behavior if any other object tries to reference your object before main().
Also, __STARTUP_HANDLE__ is not a valid identifier. Double-underscores are not allowed in any identifier (even macros), and a single-underscore followed by a capital letter is also not allowed.

If it ain't broke, don't fix it. Look out for the static initialization order issue, as the other answers say. But you really should fix that reserved identifier.
__STARTUP_HANDLE__ does work similar to a runtime library, and runtime libraries use names like that, but it's not part of the runtime library so that name isn't allowed.
#ifdef WIN32
namespace { // anonymous namespace - no outside access
class asdf {
asdf() { startup_code(); }
~asdf() { cleanup_code(); }
} x; // to create an instance
}

As long as the objects (foo.o) themselves are linked into the executable, this will work (assuming the static initialization order fiasco doesn't hit you). If you're pulling it in from a library (foo.lib), though, it won't unless you explicitly mark the object as an "active object," but I don't remember how to do that in MSVC.

On Windows and with DLL's you have the possibility to use the function DllMain that will be called at load etc
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
return TRUE;
}

Related

Shared global variable with DLL not working

I'm trying to get some code that works on the Mac to work on Windows. The code involves sharing data between a DLL, a static library and the main program. I suspect the problem arises because of the differences in the way that Unix and Windows handle global variables (see, for example, the answers here). However, I haven't figured out how to fix it. Here's a minimal example:
My Visual Studio 2019 solution contains three projects.
Project 1 makes the static library MarinaLib.lib
Header is MarinaLib.h
#pragma once
#include "Marina.h"
Class header is Marina.h
#pragma once
class Marina
{
public:
static Marina* get_marina();
protected:
static Marina* marina_instance;
};
Source file is Marina.cpp
#include "Marina.h"
Marina* Marina::marina_instance { nullptr };
Marina* Marina::get_marina()
{
if( !marina_instance )
marina_instance = new Marina();
return marina_instance;
}
Project 2 makes the DLL MarinaDLL.dll . It #defines MARINADLL_EXPORTS
First source file dllmain.cpp
// dllmain.cpp : Defines the entry point for the DLL application.
#include "framework.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Header file MarinaDLL.h is
#pragma once
#ifdef MARINADLL_EXPORTS
#define QUERY_DECLSPEC __declspec(dllexport)
#else
#define QUERY_DECLSPEC __declspec(dllimport)
#endif
QUERY_DECLSPEC void query_marina();
Second source file is marinaDLL.cpp
#include "MarinaDLL.h"
#include "..\MarinaLib\Marina.h"
void query_marina()
{
auto inst = Marina::get_marina();
}
Project 3 makes the executable MarinaExample.exe and does not #define MARINADLL_EXPORTS. It links in MarinaLib.lib and MarinaDLL.lib
The source file MarinaExample.cpp is
#include "MarinaLib.h"
#include "MarinaDLL.h"
int main()
{
auto instance = Marina::get_marina();
query_marina();
}
In the first line of main(), the code enters Marina::get_marina(). marina_instance is nullptr so the code creates a new Marina and makes marina_instance point to it. This is fine.
In the second line of main(), the code enters query_marina() and from there goes into Marina::get_marina(). At this point marina_instance is nullptr which is not what I want. I would like it to maintain its previous non-null value.
I've seen some examples of solutions to problems in similar code but they don't seem to work in my situation. Any suggestions on how to fix this?
Thanks.
add export modifier to class definition and export the whole class.
In dll and lib build define QUERY_DECLSPEC=export , in exe build as import :
class QUERY_DECLSPEC Marina
{
public:
static Marina* get_marina();
protected:
static Marina* marina_instance;
};

how to make a function return an array? for making DLL to use in VB.NET

i am trying to make a c++ DLL project in VS2017 to use in a VB.NET VS2017 project.
the c++ code;
MyCudaLib.h
#ifndef DLL3_H
#define DLL3_H
#ifdef DLL3_EXPORTS
#define DLL3_API __declspec(dllexport)
#else
#pragma message("automatic link to MyCudaLib.LIB")
//#pragma comment(lib, "MyCudaLib.lib")
#define DLL3_API __declspec(dllimport)
#endif
int* __stdcall test_array();
#endif //DLL3_H
MyCudaLib.cpp
#include <stdio.h>
#include "MyCudaLib.h"
#include <Windows.h>
#include <stdexcept>
#include <sstream>
using namespace std;
#define DLL3_EXPORTS
BOOL APIENTRY DllMain(HANDLE /*hModule*/,
DWORD ul_reason_for_call,
LPVOID /*lpReserved*/
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
int* __stdcall test_array()
{
int arr[]{ 30,50,60,70 };
return arr;
}
in VB part of the code
Private Declare Function test_array Lib "MyCudaLib.dll" () As Integer()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Console.WriteLine(test_array(0))
End Sub
is my exporting part of code is wrong? c++ part compiled wtihout error but VB part of the code wont work gives error.
System.Runtime.InteropServices.MarshalDirectiveException: ''return value' cannot arranged.
Note: My point to make a proper working function in c++ is to write a CUDA code to program the GPU. I can write and compile code in CUDA in c++ without problem. But students in my class cannot program in c++ and i can't write more complex code with c++. So, i thought, if i can use the cuda function outside the c++ environment, we all can code it with vb or other languages.
Sure your function compiles fine - it is defined as a function returning a single int and does so as well (return *arr; is equivalent to return arr[0];).
From MarshalDirectiveException
The exception that is thrown by the marshaler when it encounters a MarshalAsAttribute it does not support.
As you did not provide an English error message, I can only guess what's happening now, but there are only few options available:
You have yet another error with your marshaling not visible here.
The function is not recognised due to C++ name mangling (see below).
Incompatibility between int returned in function and expected array is recognised.
The int is interpreted as pointer – but pointer size does not match and the type cannot be marshaled at all.
If you want to return an array, you need to define your function as such:
int* getArray()
// ^
{
static int a[] = {1, 2, 3};
// ^^^^^^ we cannot return an array with local storage duration, so make it
// static, global, or allocate one on heap (new int[]; but assure the
// array to be delete[]d appropriately again to avoid memory leak)
return a; // NOT dereferenced!
}
Be aware that you have C++ name mangling applied. You might possibly prefer a C-kompatible interface:
extern "C" int* getArray();
However, you cannot return C++ data types this way like std::vector – which in most cases even is preferrable, though, as those types usually are incompatible across different implementations (DLL compiled with MSVS, EXE with GCC/MinGW) anyway.
Finally be aware that via a pointer, you lose information about array size! You need to find other means to provide this information to the user of your library.

How to reset state machines when unit testing C

I have a se of embedded C for a TI processor that need to be unit tested.
For target compilation IAR is used but i am running the tests on a Win7 machine using MinGW GCC.
In the C code there are functions containing state machines that sometimes need to be reset between tests. These state machines often keep their state variable locally static, making that task difficult if not impossible.
I'm not very C++ class savvy but i had an idea about "importing" the C functions into a wrapping C++ class as memberfunctions making it possible to just create a new object whenever a reset i needed. The code below is non functional but it illustrates my idea.
in main.cpp:
#include "statemachine.h"
using namespace std;
class stateMachineWrapper {
public:
extern void stateMachine(void);
};
int main() {
stateMachineWrapper myObject;
myObject.stateMachine();
myObject.stateMachine();
stateMachineWrapper myNewObject;
myNewObject.stateMachine();
myNewObject.stateMachine();
return 0;
}
in statemachine.h:
void stateMachine(void);
in statemachine.c:
#include <stdio.h>
void stateMachine(void)
{
static int myState = 0;
switch(myState)
{
case 0:
{
printf("Init State");
myState = 1;
break;
}
case 1:
{
printf("Second state");
break;
}
default:
{
printf("Default");
break;
}
}
}
Alterations to the statemachine.c/.h is not encouraged since it can be considered "legacy".
Any other solutions is of course welcome as well!
The wrapping won't help. The C++ code has no way of reaching the internal static variable inside the state machine written in C.
One solution is to use dynamic code loading for the C parts, that will make the early initialization code and clear the static variable.
You could also split the tests into multiple executables, that has the same effect but probably larger overhead (=tests will run more slowly).
#unwind sent me looking at dynamic code loading!
Reading these:
Dynamically load a function from a DLL and http://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/ gave me enough to concoct the following solution.
in statemachine.h:
void stateMachine(void);
in statemachine.c:
#include <stdio.h>
void stateMachine(void)
{
static int myState = 0;
switch(myState)
{
case 0:
{
printf("Init State");
myState = 1;
break;
}
case 1:
{
printf("Second state");
break;
}
default:
{
printf("Default");
break;
}
}
}
in statemachinelib.c:
#include "statemachine.h"
__declspec(dllexport) void __cdecl statemachineWrap()
{
stateMachine();
}
in main.c:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
typedef int (__stdcall *f_funci)();
int main(int argc, char **argv)
{
HINSTANCE hGetProcIDDLL = LoadLibrary("statemachinelib.dll");
f_funci funci = (f_funci)GetProcAddress(hGetProcIDDLL, "statemachineWrap");
funci();
funci();
funci();
FreeLibrary(hGetProcIDDLL); //Windows detects that no one is using this library anymore and unloads it from memory, giving the new LoadLibrary a fresh instance
hGetProcIDDLL = LoadLibrary("statemachinelib.dll");
funci = (f_funci)GetProcAddress(hGetProcIDDLL, "statemachineWrap");
funci();
funci();
funci();
return 0;
}
In this code i have omitted a lot of safety statements such as checking if the DLL could be loaded, if the function is found, whether we want too dllexport or dllimport and so on only to make it easier to grasp what is going on. If you are going to implement this in any real project you should at least read both of the resources i mentioned above.
compilation of the DLL using MinGW:
>gcc -c statemachine.c statemachinelib.c
>gcc -o statemachinelib.dll -s -shared statemachinelib.o statemachine.o -Wl,--subsystem,windows
compilation of the executable, also MinGW:
>gcc -o main.exe main.c
execution yields:
>main.exe
Init State
Second state
Second state
Init State
Second state
Second state
I'll just leave this here for a few days and if no one objects i will mark this as my accepted answer!
Edit: I have elaborated a bit and there's another (solved) question from me here with just a slight tweak Exporting a function, cast into a pointer through a DLL

Release-Build of DLL behaves unexpected

I have a VS2013 project to build a DLL which I call from Java using JNA. Everything works expected, as long as I use the Debug Configuration - but when using any optimization (Configuration Properties -> C/C++ -> Optimization -> Everything else than "Disabled (/Od)"), the behavior becomes something unexpected. I want to understand why that is the case - do I'm relying on undefined-behavior in this case?
My expectation on calling createObject() twice is: first call should return true (because instance is uninitialized and will be initialized), second call should return false (because instance is supposed to be initialized already). However, if I use the Release-Build (or activate Optimizations in Debug-Build) createObject() is returning true for every consecutive call.
My C++ Code:
#include <windows.h>
#include <memory>
#define DLL_EXPORT
#ifdef DLL_EXPORT
# define CALLCONV extern "C" __declspec(dllexport)
#else
# define CALLCONV extern "C" __declspec(dllimport)
#endif
class MyType{
};
std::unique_ptr<MyType> instance = nullptr;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
switch (fdwReason){
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
default:
break;
}
return TRUE;
}
CALLCONV bool createObject(){
bool retVal = true;
if (instance == nullptr){
instance = std::unique_ptr<MyType>(new MyType());
}else{
retVal = false;
}
return retVal;
}
Just for reference, my calling JNA code (but I guess, the same problem would be there, if I call it from native code as well):
import com.sun.jna.Library;
import com.sun.jna.Native;
public class main {
public interface TestLibrary extends Library {
TestLibrary INSTANCE = (TestLibrary)Native.loadLibrary("Test", TestLibrary.class);
boolean createObject();
}
public static void main(String[] args) {
try {
System.out.println(TestLibrary.INSTANCE.createObject());
System.out.println(TestLibrary.INSTANCE.createObject());
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load.\n" + e);
System.exit(1);
}
}
}
The size of bool is implementation-dependent. JNA assumes a default conversion to boolean from a native int. You should ensure your native code is returning something with a well-defined size so that JNA can do the conversion reliably.
JNA requires well-defined sizes for everything in order to perform Java to native translation correctly.

Can a dll file be initialized - A Dll constructor

I am currently importing a function out of my dll in the following way in a C# application.
[DllImport("C:\\File.dll")]
public static extern int SomeMethod(int A);
My dll file is written in C++. This method is also defined in the .def file of the dll.
Currently whenever this method is called in the first ever attempt a couple of other methods are called , these methods set up the grounds for this method. However these methods only need to be called once. These methods are never called again/ I wanted to know is there a way to call a group of methods (initializers) as soon as a dll file is loaded. Is there anything as a dll constructor ?
I have something like this in my dllmain.cpp could entering something in there accomplish this task
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DllMain is the closest to a DLL "constructor" (and the correct place to do initialization is in the case label for DLL_PROCESS_ATTACH). However a more realistic constructor would be that of a COM class instantiated by the C# code. In that case the constructor would be called for every instance of the class that you create (just like for a C# class). Create an ATL project in Visual C++ and it will generate code like this for you:
class ATL_NO_VTABLE CMyClass :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMyClass, &CLSID_MyClass>,
public IMyClass
{
public:
CMyClass()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_MYCLASS1)
BEGIN_COM_MAP(CMyClass)
COM_INTERFACE_ENTRY(IMyClass)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
...
In the CMyClass constructor or in the FinalConstruct method you can perform the initialization code for the object. Also add your SomeMethod method to this class (and to the IDL interface in the IDL file).
Then you would use that class in C# like this:
MyClass mc = new MyClass(); // CMyClass::CMyClass and CMyClass::FinalConstruct are called in C++
mc.SomeMethod(); // CMyClass::SomeMethod is called in C++