Here are my codes for PoC:
a.h: which implements a singleton method to create A instance
#pragma once
class A
{
public:
int a;
static A& Instance() {
static A a;
return a;
}
};
b.h: which declares a function will try to create an A instance inside, and output the address of it.
#pragma once
void test_b();
b.cc: The implementation of test_b
#include "b.h"
#include <iostream>
#include "a.h"
void test_b() {
auto &a = A::Instance();
std::cout << "a address in test_b: " << (void *)(&a) << std::endl;
}
and c.cc: test_c which do the same things as test_b, and call test_b and test_c in main to check if the singleton is working.
#include <iostream>
#include "a.h"
#include "b.h"
void test_c() {
auto &a = A::Instance();
std::cout << "a address in test_c: " << (void *)(&a) << std::endl;
}
int main() {
test_b();
test_c();
return 0;
}
I using the b.cc to build a shared library libb.so in windows(libb.dll), and using c.cc to create the test_app which links with the shared library.
I've tested the above codes in Linux and Windows(MinGW), but I've got different results.
Under linux the output is like:
a address in test_b: 0x601174
a address in test_c: 0x601174
And under MinGW the output is like:
a address in test_b: 0x7ff87df93070
a address in test_c: 0x7ff731ef30b0
The makefile I used for the build.
Makefile:
test_app: c.cc libb.so
g++ -o $# $^ -lb
libb.so: a.h b.cc
g++ -o $# -fPIC -shared b.cc
Makefile.mingw
test_app.exe: c.cc libb.dll
g++ -o $# $^ -lb -L.
libb.dll: a.h b.cc
g++ -o $# -fPIC -shared b.cc
I know implementing Singleton in the header file is not a good practice, but if anyone could help to explain why?
As far as the language is concerned, the lvalue returned by A::Instance must always refer to the same object within the execution of the program. If a language implementation deviates from that, then it doesn't conform to the standard.
why?
You are using shared libraries which are an extension of the language. As you've witnessed, using this language extension causes the language implementation to deviate from the guarantees given by the standard.
You can work around the issue by defining the instance getter as a non-inline function in a single translation unit, rather than as an inline function. Another way is to use language implementation specific function attributes to control the shared library behaviour as per the documentation of the language implementation (dllexport, dllimport in MSVC).
Sidenote: Singleton pattern requires that the class is encapsulated such that no instances besides the static one can be created. The example is just a static local object and technically not a singleton since the constructor isn't encapsulated.
Related
Im trying to write a wrapper in c++/cli for an DLL, which code i dont have, only DLL file and header but i created lib file through VS command prompt. When i`m trying to build solution i receive this errors:
DotNetWrappOfAsterSdkDll.obj : error LNK2028: unresolved token (0A00002E) "void __stdcall MuteClearLastError(void)" (?MuteClearLastError##$$FYGXXZ) referenced in function "public: void __clrcall DotNetWrappOfAsterSdkDll::WrapperClass2::doMuteClearLastError(void)" (?doMuteClearLastError#WrapperClass2#DotNetWrappOfAsterSdkDll##$$FQ$AAMXXZ)
DotNetWrappOfAsterSdkDll.obj : error LNK2019: unresolved external symbol "void __stdcall MuteClearLastError(void)" (?MuteClearLastError##$$FYGXXZ) referenced in function "public: void __clrcall DotNetWrappOfAsterSdkDll::WrapperClass2::doMuteClearLastError(void)" (?doMuteClearLastError#WrapperClass2#DotNetWrappOfAsterSdkDll##$$FQ$AAMXXZ)
I tried to create my own DLL and include it to the wrapper, and its working perfectly
here dll created by me which i can use in c++/cli wrapper:
//header file
#pragma once
#define DLLEXP __declspec( dllexport )
namespace Computations {
DLLEXP void someMethod(int number);
}
//cpp file
#include "Computations.h"
#include <iostream>
#include <time.h>
//#include "pnl/pnl_random.h"
using namespace std;
void Computations::someMethod(int number)
{
std::cout << "something "<<number*number << endl;
}
and here is part of header of DLL which i want to use:
#ifndef MUTEIFC_H
#define MUTEIFC_H
#include <Windows.h>
#ifdef MUTEIFC_LIBRARY
# define MUTEAPI extern "C"__declspec(dllexport)
#else
# define MUTEAPI __declspec(dllimport)
#endif
#define MUTECALL __stdcall
/** \ingroup init */
/** Initialization of the ASTER SDK library
* \returns TRUE - success, FALSE - failure (use \ref MuteLastErrorCode or/and \ref MuteLastErrorInfo to get
* failure cause)
* \note This function will require Administrative privileges on the first call on a given computer.
*/
MUTEAPI BOOL MUTECALL MuteIfcInitialize(VOID);
/** \ingroup init */
/** Finialization of the ASTER SDK library
*/
MUTEAPI VOID MUTECALL MuteIfcFinalize(VOID);
/** \ingroup errors*/
/** Clears the calling thread's last-error code and description.
* The last-error is maintained on a per-thread basis. Multiple threads do not overwrite each other's last-error.
*/
MUTEAPI VOID MUTECALL MuteClearLastError(VOID);
#endif // MUTEIFC_H
and my c++/cli code :
//header file
#pragma once
#include "Computations.h"
#include "muteifc.h"
using namespace System;
namespace DotNetWrappOfAsterSdkDll
{
public ref class WrapperClass2
{
public:
void doMuteClearLastError();
};
public ref class WrapperClass
{
private:
public:
void getPriceCallEuro(int number);
};
}
//cpp file
#include "DotNetWrappOfAsterSdkDll.h"
using namespace DotNetWrappOfAsterSdkDll;
using namespace Computations;
namespace DotNetWrappOfAsterSdkDll
{
//this dont work
void WrapperClass2::doMuteClearLastError() {
MuteClearLastError();
}
//this works great
void WrapperClass::getPriceCallEuro(int number) {
someMethod(number);
//MuteIfcFinalize();
}
}
Please tell me what i'm doing wrong
You probably didn't add the lib that contains the function reference to the linker options.
Either the lib contains he code it self or it has a reference to the DLL that must be loaded. The linker will bring your code and the DLL (or static lib) code together...
I have a question similar to this one. I am trying to compile a DLL for windows similar to how Visual Studio would, except with CLion and CMake. I've tried the answer in the question, as well as the steps shown here, but I still get an error while injecting.
My dll code is very simple, a similar dll compiled in visual studio works fine:
#include <windows.h>
#include <iostream>
using namespace std;
void hello() {
AllocConsole();
freopen("CONOUT$", "w", stdout);
cout << "Hello, World!" << endl;
}
bool __stdcall DllMain(HMODULE /*module*/, DWORD reason, LPVOID /*reserved*/) {
if (reason == DLL_PROCESS_ATTACH) hello();
return true;
}
Also, here's what I tried in CMakeLists.txt: sorry, there should have been a space between PROJECT_NAME and MODULE
cmake_minimum_required(VERSION 3.9)
project(PROJECT_NAME)
include (GenerateExportHeader)
set(CMAKE_CXX_STANDARD 17)
add_library(PROJECT_NAME MODULE main.cpp)
set_target_properties(PROJECT_NAME PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
GENERATE_EXPORT_HEADER(PROJECT_NAME
BASE_NAME PROJECT_NAME
EXPORT_MACRO_NAME PROJECT_NAME_EXPORT
EXPORT_FILE_NAME PROJECT_NAME_Export.h
STATIC_DEFINE PROJECT_NAME_BUILT_AS_STATIC)
You have two options:
Add the BUILD_SHARED_LIBS variable to CMake's cache as a boolean value then check it. This will modify the behaviour of the add_library command to make a shared library i.e. a DLL file on Windows.
Explicitly create the library as shared: add_library(PROJECT_NAMEMODULE SHARED main.cpp)
BUILD_SHARED_LIBS variable documentation: https://cmake.org/cmake/help/v3.10/variable/BUILD_SHARED_LIBS.html
How can I use functions from my file.c in Objective C
I tried #include < file.c > in file2.m where I want to call this functions and got Lexical or Prepocesor Issue < file.c > not found and when I use #include "file" i got Apple Mach-O Linker (ID) Error. Same errors when I use #import instead of #include.
If in "file.m" you have a function like this:
void hello()
{
printf("Hello world!");
}
You also have to create a header file possibly called "file.h" in which you only declare the function but don't actually implement it;
void hello();
Then you have to #import or #include thw file.h file from file2.m.
Does your file.c have a file.h with the function declarations? You will want to #include that, and also make sure that file.c is compiled and linked in.
I've read that, the objective-c programs need objective-c runtime to run.
AFAIK, both C/C++ programs don't require any runtime environments to run. as the generated binary code is being executed directly by the underlying OS.
So this means that Objective-c programs require a redundant layer to run, correct? and If so, is this layer seems like Java VM and .net runtime or seems like Qt runtime (in flavor of some additional libraries)?
EDIT:
After some read, I found that, the objc compiler generates some more information in the generated compiled code that is responsible of many things such as method passing (objc_sendMsg(), introspection and others)
Thanks.
The compiled code is native but you need an additional library (the runtime) which does all the object and message handling (lookup, invocation etc.). There is no virtual machine involved. So it is more like QT than Java runtime.
[Update]
Since the C++ message binding behaviour is not obvious to programmers of more dynamic OO languages (e.g.: Objective-C or Smalltalk) - like me - I wrote a small C++ test app which demonstrates the effect of the virtual keyword on the choice of the method to call.
#include <iostream>
class Test1 {
public:
Test1();
void test1();
void test2();
};
class Test2 : Test1 {
public:
Test2();
void test1();
void test2();
};
Test1::Test1() {}
void Test1::test1() { std::cout << "T1:t1" << std::endl; }
void Test1::test2() { std::cout << "T1:t2" << std::endl; }
Test2::Test2() {}
void Test2::test1() { std::cout << "T2:t1" << std::endl; }
void Test2::test2() { std::cout << "T2:t2" << std::endl; }
int main(int argc, char **argv)
{
Test1 *t11 = new Test1();
Test1 *t12 = (Test1 *)(new Test2());
Test2 *t2 = new Test2();
t11->test1();
t11->test2();
t12->test1();
t12->test2();
t2->test1();
t2->test2();
return 0;
}
An Objective-C programmer would expect a output of
T1:t1
T1:t2
T2:t1
T2:t2
T2:t1
T2:t2
since t12 is actually a Test2 which was casted to Test1.
The actual output is
T1:t1
T1:t2
T1:t1
T2:t2
T2:t1
T2:t2
because C++ (by default, i.e. without virtual) statically binds the call to test1 based on the type it knows at compile time which is Test1 (due to the cast).
I made a DLL with a function named "render()" and I want to load it dynamically to my application, but GetProcAddress cannot find it. Here's the DLL .h:
#ifdef D3D_API_EXPORTS
#define D3D_API_API __declspec(dllexport)
#else
#define D3D_API_API __declspec(dllimport)
#endif
D3D_API_API void render();
And here's DLL .cpp:
#include "stdafx.h"
#include "D3D_API.h"
#include <iostream>
D3D_API_API void render()
{
std::cout << "method called." << std::endl;
}
Here's the application that tries to use that function:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE myDLL = LoadLibrary( L"D3D_API.dll" );
if (myDLL == NULL) {
std::cerr << "Loading of D3D_API.dll failed!" << std::endl;
}
typedef void (WINAPI *render_t)();
render_t render = (render_t)GetProcAddress( myDLL, "render" );
if (render == NULL) {
std::cerr << "render() not found in .dll!" << std::endl;
}
return 0;
}
My goal is to make a 3D engine that supports both D3D and OpenGL through their own .DLLs using a unified API. I looked at the .dll in notepad and there was a string "render".
The function you export is treated as a C++ function (because of *.cpp file extension) and so C++ name mangling is used to decorate the exported function name. If you use the Dependency Walker tool from Microsoft to inspect your created DLL you will see the functions full name.
You can either use that decorated name in your import code or force the compiler to export your function in C style, that is, in its undecorated form that your current import code expects.
You can tell the compiler to do so by adding extern "C" to your functions signature. Something like this:
extern "C" D3D_API_API void render();
Now your import code should work as expexted.
As the comment to the answer says:
using 'extern "C"' will remove any C++ name mangling, but still leaves
C name mangling. In order to export the plain names you should look at
using a .DEF file. See
blogs.msdn.microsoft.com/oldnewthing/20120525-00/?p=7533
You need to add a new file with .DEF extension to your project, with similar to this contents:
LIBRARY "MyRenderLib"
EXPORTS
render
Then in your DLL header you don't use __declspec(dllexport), but only extern "C"
extern "C" void render();