Build Windows DllMain DLL with CMake - cmake

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

Related

Why singleton in headers not work for Windows/MinGW?

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.

Xcode 11 Objective C++ - Can't separate implementation from Header in ObjectiveC++ Project

I have created an Xcode standard Objective-C Project wanting to test integration with C++.
I have renamed my file accordingly to .mm etc.
I have created a C++ Class with a .hpp header and a .cpp imp file.
This is the header
class a {
private:
int anInt = 1;
public:
int getAnInt();
};
this is the imp
#include "PrismMatricies.hpp"
int a::getAnInt() {return anInt;}
in my ViewController.mm file I do this after importing the .hpp header
a ar;
NSLog(#"Some Log %i", ar.getAnInt());
Build Error Code in Xcode =
Undefined symbol: a::getAnInt()
If I move the function definition inside the header like this
class a {
private:
int anInt = 1;
public:
int getAnInt();
};
int a::getAnInt() {return anInt;}
The project works
Can anyone explain this to me as I simply don't get it
Note that "undefined symbol" is a link error, not a compile error, and your code certainly looks correct.
You will get that error if your .cpp isn't being linked into your build target. Make sure it's included in your build target's "compile sources" list. (You can also check that the target membership box is ticked in the File Inspector utility pane.)

Proper way to link static library into shared library with CMake

I have a CMake project with the following structure
root
|- common
|- Bitmap.h
|- Bitmap.cpp
|- BytesUtils.h
|- BytesUtils.cpp
|- encoding
|- jni
|- impl.cpp
|- main.cpp
The project will create two artifacts: an executable using main.cpp, and a shared library using the source code in jni/ to be loaded by JNI. They both rely on the source files in common and encoding.
Here's my root/CMakeLists.txt
file(GLOB_RECURSE COMMON_SOURCE
"common/*.h"
"common/*.cpp"
)
file(GLOB_RECURSE ENCODING_SOURCE
"encoding/*.h"
"encoding/*.cpp"
)
add_library(common STATIC ${COMMON_SOURCE})
add_library(encoding STATIC ${ENCODING_SOURCE})
add_executable(main main.cpp)
target_link_libraries(main common)
target_link_libraries(main encoding)
add_subdirectory(jni)
and here's the jni/CMakeLists.txt
set(JAVA_HOME "/usr/lib/jvm/jdk1.8.0_221")
#set(JAVA_HOME "/usr/lib/jvm/java-8-openjdk-amd64/")
include_directories(${JAVA_HOME}/include)
include_directories(${JAVA_HOME}/include/linux)
file(GLOB_RECURSE JNI_SOURCE
"*.h"
"*.cpp"
)
add_library(lqf SHARED ${JNI_SOURCE})
target_link_libraries(lqf common)
target_link_libraries(lqf encoding)
When I load the library using JNI I got the following error:
/usr/lib/jvm/jdk1.8.0_221/bin/java: symbol lookup error: /home/harper/git/lqf/lqf-cpp/cmake-build-debug/lib/liblqf.so: undefined symbol: _ZN6common6BitmapC1EPmj
Using nm to look at the generated so, I discovered that all functions from common/Bitmap.cpp are marked as undefined symbol
U _ZN6common6Bitmap10appendBitsEhj
U _ZN6common6Bitmap11moveForwardEj
U _ZN6common6BitmapC1EPmj
But functions from other source code under common/ are included properly
0000000000002894 T _ZN6common10BytesUtils19readIntLittleEndianEPhPj
00000000000028d0 T _ZN6common10BytesUtils35readIntLittleEndianPaddedOnBitWidthEPhPjh
00000000000029d3 T _ZN6common10BytesUtils18readUnsignedVarIntEPhPj
The only difference I can see is that Bitmap is a class and BytesUtils is a collection of functions.
Bitmap.h
#include <cstdint>
namespace common {
class Bitmap {
public:
Bitmap(uint64_t *data, uint32_t offset);
void appendWord(uint64_t *word, uint32_t count);
void appendBits(uint8_t bit, uint32_t rep);
void moveForward(uint32_t count);
};
}
Bitmap.cpp:
#include "Bitmap.h"
common::Bitmap::Bitmap(uint64_t *data, uint32_t offset) {...}
void common::Bitmap::appendBits(uint8_t bit, uint32_t repetition) {...}
void common::Bitmap::appendWord(uint64_t *word, uint32_t count) {...}
void common::Bitmap::moveForward(uint32_t count) {...}
So what is a proper way to build the shared library so these symbols are included?
Update # Sep 24, 2019 21:32
This is caused by dependencies between static libraries. The encoding lib uses common lib but I failed to add the target_link_libraries between them. After adding target_link_libraries(encoding, common) the symbol tables is fixed.
This is caused by dependencies between static libraries. The encoding lib uses common lib but I failed to add the target_link_libraries between them. After adding target_link_libraries(encoding common) the symbol tables is fixed.

Fatal error LNK1104 with Visual Studio 2017 and CMake

I have the following header in a file matrix_utils.hpp :
#include "someIncludes"
void ReadMtxMatrixHeader(){}
int ScanCurrentLine() {}
void ReadMtxMatrixHeader( {}
template<typename T> void RTS_EXPORTS ReadMtxMatrixToCSR() {}
template<typename T> void RTS_EXPORTS ReadMtxMatrixToColMajorArray() {}
The implementation here is not important so I left empty brackets.
The RTS_EXPORTS is a macro for :
# define RTS_EXPORTS __declspec(dllexport) // if WIN32
# define RTS_EXPORTS __attribute__ ((visibility ("default"))) // if GNUC >=4
This header is part of a module called "utils" and is used by a target "rts_test_utils". This code works perfectly fine on Linux and on Windows using Cygwin and CLion. But as soon as I try to use Visual Studio 2017 (my project is a CMake project), I get this error when building "rts_test_utils" :
$buildPath\build\x86-Debug\modules\utils\LINK : fatal error LNK1104:
cannot open file '..\..\lib\Debug\rts_utilsd.lib'
Visual Studio generates the DLL for rts_utils, but not the lib. If I add a dummy class like the one below to "matrix_utils.hpp", then it works and it creates a rts_utilsd.lib. Why ?
class RTS_EXPORTS Foo{};
Following comment from oLen, I added the following code in my matrix_utils.cpp (could have been in the header too) to force compiler to see that a template function is exported:
template void RTS_EXPORTS
ReadMtxMatrixToColMajorArray(std::vector<float> &col_major_host_ptr,
const std::string filename, bool is_one_based);
I know I will use this function with float specialization, so it's not even wasted.

Singleton MFC extension DLL

I declare a singleton on a MFC extension DLL, like this:
//header file: SingleTon.h
class AFX_EXT_CLASS CMySingleton
{
public:
static CMySingleton* Instance()
{
if(!singleton)
singleton = new CMySingleton();
return singleton;
}
int a;
// Other non-static member functions
private:
CMySingleton() {}; // Private constructor
CMySingleton(const CMySingleton&); // Prevent copy-construction
CMySingleton& operator=(const CMySingleton&); // Prevent assignment
virtual ~CMySingleton() {};
static CMySingleton* singleton;
};
And in a cpp file I code the following line:
CMySingleton* CMySingleton::singleton = NULL;
Code 2:
CMySingleton *a;
a = CMySingleton::Instance();
The problem is when I code "code 2" in a Regular Dll, all works fine, but when I code "code 2" in another MFC extension DLL gives an error:
unresolved external symbol "private: static class CMySingleton* CMySingleton::singleton" (?singleton#CMySingleton##0PAV1#A)
I check correctly all the dependencies, via Project Dependencies.
Any idea?
The problem is in the AFX_EXT_CLASS macro.
#ifdef _AFXEXT
#define AFX_EXT_CLASS __declspec(dllexport)
#else
#define AFX_EXT_CLASS __declspec(dllimport)
#endif
Extension dll defines _AFXEXT and your class is exported, and main app (or a regular dll) doesn't define it so it's imported. But your second extension dll also defines _AFXEXT and your class declaration uses dllimport instead of dllexport and you get a linker error. The solution is to create your own macro for both dlls and use them instead of AFX_EXT_CLASS:
#ifdef EXTENSION_ONE
#define EXT_CLASS_ONE __declspec(dllexport)
#else
#define EXT_CLASS_ONE __declspec(dllimport)
#endif
Create EXTENSION_TWO and EXT_CLASS_TWO for your second dll. Define EXTENSION_ONE only in your first extension dll project, and EXTENSION_TWO only in your second extension dll project.