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.
Related
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.)
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 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.
Help!
I'm totally exhausted/frustrated with what seems to be a reasonably easy task. I’m not sure what I'm doing wrong; let alone if I'm doing it correct. I'm "required" to use an existing library (a C static library – over 100,000 lines of straight C code) in developing a WPF application (VS 2010, C# 4.0). Oh, and I can't touch the existing C code - use it as is!
I've read so many postings (advanced topics, how-to, etc), yet I'm so new to C++/CLI that it's just not making sense. From what I've read the best approach is to wrap the C static library as follows:
Unmanaged C static library <---> C++/CLI managed wrapper DLL <--->
managed WPF application
This is the stripped down C header file:
/* Call this function to execute a command. */
int issue_command(int command, long param1, long param2);
/* Completion call back function; you must supply a definition. */
extern int command_completed(int command, long param1, long param2);
struct struct_command_str
{
char command_str[10];
char param1_st[2];
char param2_st[2];
char success;
};
/* You must supply definitions to the following extern items. */
extern int command_status;
extern struct struct_command_str command_str;
The problem(s):
What I can’t seem to do correctly is provide a C++/CLI implementation for the call back functions, and the two extern items (command_status and struct command_str).
Can someone provide a sample C++/CLI implementation for the above missing call back functions and externs?
Thanks in advance for your assistance.
in your C++/CLI managed wrapper project, add 2 files :
a .c file :
extern void doSomething();
int command_status = 0;
struct_command_str command_str = { "command1", "p1", "p2", 't' };
int command_completed(int command, long param1, long param2) {
...
command_status = 1;
...
doSomething();
...
command_status = 2;
...
return 3;
}
a cpp file
void doSomethingManagedWrapper() {
...
call managed code
...
}
void doSomething() {
doSomethingManagedWrapper();
}
when you implement these in your c++/cli module, use the same signature shown in the c header file,but prefixed with extern "C".
also put an extern "C" block around the #include of the C header file.
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();