C++ dll and name mangling issue - c++

I am trying out a simple test DLL project. Under my solution, I have two projects - first C++ Dll (library) and second C++ exe (driver). Below I've attached a snapshot of the basic project setup:
dllmain.h
#ifndef DLLMAIN_H_
#define DLLMAIN_H_
#ifdef FFMPEGLIB_EXPORTS
#define FFMPEGLIB_API __declspec(dllexport)
#else
#define FFMPEGLIB_API __declspec(dllimport)
#endif // FFMPEGLIB_EXPORTS
static void TestFoo();
extern "C" FFMPEGLIB_API void Test(int* num);
extern "C" FFMPEGLIB_API void ProxyFoo();
#endif
dllmain.cpp
#include "dllmain.h"
#include "A.h"
void TestFoo()
{
A a;
a.foo();
}
void Test(int* num)
{
*num = *num + 1;
}
void ProxyFoo()
{
TestFoo();
}
driver.cpp
#include <iostream>
#include "dllmain.h"
int main(int argc, char** argv)
{
int mum = 4;
Test(&num);
std::cout << num;
ProxyFoo();
return 0;
}
The library project compiles normally, but the exe fails to compile with a linker error:
Code Description Project File
LNK2001 unresolved extern symbol _imp_ProxyFoo driver driver.obj
LNK2001 unresolved extern symbol _imp_Test driver driver.obj
LNK1120 2 unresolved externals driver driver.exe
I have two questions here:
Why does the function name of dllmain.h get mangled in spite of being marked as extern "C"?
Why can I not create an instance of test class A from extern methods? What would be a good way of doing that?

Why the function name of dllmain.h getting mangled in spite being
marked as extern "C"?
Because __declspec(dllimport).
Why can I not create instance of test class A from extern methods?
What would be good way of doing it?
I think that's fine, but you didn't provide any class A code. Just do this:
class __declspec(dllexport) A
{
/* ... */
};
Why EXE compile failed?
This is because you have not imported the LIB file of the DLL into the project.
There are two ways to import it:
Add #program comment(lib, "<YOUR_LIB_FILE>.lib") to the code file.
Add <YOUR_LIB_FILE>.lib to Properties -> Linker -> Input -> Additional Dependencies.
Microsoft documentation: https://learn.microsoft.com/en-us/cpp/build/importing-and-exporting

You need to put the extern "C" thing around your function definitions that you intend to export in dllmain.cpp so it matches the linkage of your declaration.
Also, you need to do the declexport thing too.
extern "C"
{
__declspec(dllexport) void Test(int* num)
{
*num = *num + 1;
}
__declspec(dllexport) void ProxyFoo()
{
TestFoo();
}
}

Related

error LNK2019 when importing functions from a DLL

I'm learning how to build a DLL and call it from another project(I also want the DLL can be called not only by C/C++ but also by Python). Here is my code for building the DLL:
callbacktesetDLL.h:
#ifdef CALLBACKTESTDLL_EXPORTS
#define CALLBACKTESTDLL_API __declspec(dllexport)
#else
#define CALLBACKTESTDLL_API __declspec(dllimport)
#endif
typedef int(CALLBACK *p)(char*);
CALLBACKTESTDLL_API int __stdcall StrToInt(char*);
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char*, int b);
callbacktestDLL.cpp:
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
CALLBACKTESTDLL_API int __stdcall StrToInt(char* StrInput)
{
int IntResult;
IntResult = atoi(StrInput);
return IntResult;
}
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char* StrInput, int b)
{
int a = FuncP(StrInput);
if (a>b)
{
return "a is bigger than b";
}
else
{
return "b is bigger than a";
}
}
And a Source.def file:
LIBRARY
EXPORTS
StrToInt #1
NumCompare #2
With the code above, I got callbacktestDLL.dll and callbacktestDLL.lib. With depends, the functions' names in the DLL can be shown:
Now I want to call the functions in the DLL from another project:
CallDLL.h:
#pragma comment(lib,"callbacktestDLL.lib")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(*p)(char*);
extern "C" _declspec(dllimport) int StrToInt(char* InpuString);
extern "C" _declspec(dllimport) char* NumCompare(p FuncP, char*, int b);
CallDLL.cpp:
#include "stdafx.h"
int main()
{
p FuncP_R = StrToInt;
NumCompare(FuncP_R, "1234", 40);
return 0;
}
However, when I run the project, it told me:error LNK2019: unresolved external symbol __imp__StrToInt and error LNK2019: unresolved external symbol __imp__NumCompare. I've already copy the .lib and .dll files under the CallDLL project's root folder. Why this happens? How can I solve it? Thank you for your attention.
I finally made it. Here is the details:
The files that generate the DLL:
callbacktestDLL.h:
typedef int(CALLBACK *p)(char*);
extern "C" __declspec(dllexport) int __stdcall StrToInt(char* InputString);
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b);
callbacktestDLL.cpp:
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
extern "C" CALLBACKTESTDLL_API int __stdcall StrToInt(char* InputString)
{
int IntResult;
IntResult = atoi(InputString);
return IntResult;
}
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b)
{
int a = FuncP(InputString);
if (a>b)
{
return "a is bigger than b\n";
}
else
{
return "b is bigger than a\n";
}
}
Comparing to the former files in the post, I removed the .def file and added extern "C" ahead of each function declaration and definition. Then I generate a new .dll and .lib files and copy them to the CallDLL projects' root folder. I used depends to see the functions' names in the DLL:
I also changed the CallDLL's file like this:
CallDLL.h:
#pragma comment(lib,"callbacktestDLL")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(__stdcall *p)(char*); //same as typedef int(CALLBACK *p)(char*) in callbacktestDLL.h
extern "C" _declspec(dllimport) int __stdcall StrToInt(char* InputString); //exactly same as what's in callbacktestDLL.h apart from dllimport
extern "C" _declspec(dllimport) char* __stdcall NumCompare(p FuncP, char* InputString, int b); //exactly same as what's in callbacktestDLL.h apart from dllimport
CallDLL.cpp:
#include "stdafx.h"
int main()
{
p FuncP_R;
char* a = "1234";
FuncP_R = StrToInt;
printf(NumCompare(FuncP_R, a, 42));
return 0;
}
It worked as expected. I think one of the mistakes I made is missing __stdcall when importing. Maybe there are also mistakes about the name mangling. I'll keep testing it.
You should always include the same header file to define a consistent interface. Creating different header files is error prone. The next change to the interface might make the interface incompatible.
There is a slight difference between the module that implements the functions to the module that uses the functions. The difference is the __declspec(dllimport) or __declspec(dllexport). That's why the header files contains the
# ifdef CALLBACKTESTDLL_EXPORTS
Your module that implements the functions also export them. Therefore you must defined the symbols in the project settings. If you compile at the command line you have to add the /D CALLBACKTESTDLL_EXPORT to the compiler arguments.
BTW: If you have defined CALLBACKTESTDLL_EXPORT your macro CALLBACKTESTDLL_API contains the __declspec(dllexport). This causes the linker to create the DLL export table. The .DEF is not necessary. You should remove it because..... it defines the interface again (at a different level).

Creating a DLL in C++ to import C++ DLL in VS 2005

I'm trying to link C++ DLL into a new C++ DLL which i will create,
I've followed the below tutorial step by step and many others but something wrong the "GetProcAddress" function returns NULL "http://www.dreamincode.net/forums/topic/118076-dlls-explicit-linking/"
This is the Prototype of the function i try to call from the DLL :
int RemoveAllDataFile( unsigned int id );
the function returns with 1 so the DLL is loaded successfully.
typedef int (*funcRemoveAllDataFile) (int);
int load_dll_ARbnet(int x)
{
/* Retrieve DLL handle.*/
HINSTANCE hDLL = LoadLibrary("ArbNet2Remote.dll");
if (hDLL == NULL)
{
return 0;
}
else
{
}
/*Get the function address*/
funcRemoveAllDataFile RemoveAllDataFile = (funcRemoveAllDataFile)GetProcAddress(hDLL, "RemoveAllDataFile");
if (RemoveAllDataFile)
{
return 2;
}
else
{
return 1;
}
}
The function you export from the other DLL should be declared extern "C" if using C++ source. If should be exported either with a .def file or using __declspec(dllexport):
Here's a typical DLL header file that works with .c or .cpp and both calling conventions:
#ifdef MYAPI_EXPORTS
#define MYAPI __declspec(dllexport)
#else
#define MYAPI __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
MYAPI int __cdecl func1(int x);
MYAPI int __stdcall func2(int x);
#ifdef __cplusplus
}
#endif
DLL source:
#define MYAPI_EXPORTS
#include "x.h"
int func1(int x)
{
return x*2;
}
int __stdcall func2(int x)
{
return x*3;
}
And usage:
#include <windows.h>
#include <stdio.h>
typedef int (__cdecl *FUNC1)(int);
typedef int (__stdcall *FUNC2)(int);
int main()
{
HINSTANCE hDLL = LoadLibrary("x");
FUNC1 func1 = (FUNC1)GetProcAddress(hDLL, "func1");
#ifdef _WIN64
FUNC2 func2 = (FUNC2)GetProcAddress(hDLL, "func2");
#else
FUNC2 func2 = (FUNC2)GetProcAddress(hDLL, "_func2#4");
#endif
printf("%d %d\n",func1(5),func2(5));
}
Name decoration can be discovered with dumpbin /exports <dll>. Note that x64 and x86 differ. Below is for x86:
ordinal hint RVA name
2 0 00001010 _func2#4
1 1 00001000 func1
Look at the DLL's actual exports, such as with a reporting tool like TDUMP or similar. The function you are looking for is not being exported as "RemoveAllDataFile" like you are expecting. It is actually being exported like "_RemoveAllDataFile" instead, or even something like "_RemoveAllDataFile#4".
If you are compiling the original DLL, and want the function exported as "RemoveAllDataFile", you will have to wrap the declaration of the exported function with extern "C" to remove any C++ name mangling from the exported name. Depending on your C++ compiler, you may also need to use a .def file to remove the leading underscore that is imposed by the __cdecl calling convention. When using C linkage, some C++ compilers export __cdecl functions with the leading underscore (such as Borland) and some do not (such as Microsoft).
But if you are not recompiling the original DLL, then you have no choice but to look at the DLL's exports and change your GetProcAddress() call to use the proper name that is actually being exported.

Having trouble importing function from C++ dll error LNK 2019

I am trying to write and test a dll file in C++ that I can call whenever I want filesystem level access to things. I am currently having a huge headache when trying to access the methods in this dll in C++. Strangely enough, I was able to call the code in a separate C# program with little trouble, but I want to get an understanding of how dll interaction works in C++.
And this is the .cpp for my dummy executable that should only call my "newMain" test method.
// dummy.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
//#pragma comment(lib,"visa32.lib")
#pragma message("automatic link to adsInterface.dll")
#pragma message(lib, "adsInterface.lib"
extern "C" int __stdcall newMain();
int _tmain(int argc, _TCHAR* argv[])
{
newMain();
std::string i;
std::cin >> i
return 0;
}
The problem is, when I run it I get this error:
error LNK2019: unresolved external symbol _newMain#0 referenced in function _wmain
error LNK1120: 1 unresolved externals
Here is the .h for adsInterface:
// adsInterface.h
#ifndef ADSINTERFACE_H
#define ADSINTERFACE_H
/* //save this for later i have no clue how this really works.
#ifdef ADSAPI_EXPORTS
#define ADSAPI __declspec(dllexport)
#else
#define ADSAPI __declspec(dllexport)
#endif
*/
namespace ADSInterface
{
//test method. should print to console.
__declspec(dllexport) int __stdcall newMain();
void hello();
}
#endif
and here is my .cpp for adsInterface:
// adsInterface.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "adsInterface.h"
#include <iostream>
namespace ADSInterface
{
/* this is where the actual internal class and other methods will go */
void hello()
{
std::cout << "hello from the DLL!" << std::endl;
}
__declspec(dllexport) int __stdcall newMain()
{
hello();
return 0;
}
}
I'll also include the .def file i used when compiling the dll:
; adsInterface.def - defines exports for adsInterface.dll
LIBRARY ADSINTERFACE
;DESCRIPTION 'A C++ dll that allows viewing/editing of alternate data streams'
EXPORTS
newMain #1
Strangely enough, I was able to import the method in C# with this line (I did not have to include a .lib file either):
[DllImport("./adsInterface.dll")] private static extern void newMain();
And it ran when I called it normally:
newMain();
I've been reading many different guides on how to import dll functions, and I've reached the point where I think I'm just mangling together different ways of importation between the languages and just making a mess of things. If anyone is able to provide some insight on how I should be importing dll methods in C++ that would be much appreciated.
delete this declaration:
extern "C" int __stdcall newMain();
and call ADSInterface::newMain() from _tmain.
In the posted code you did not define anything matching that declaration, did you?
Alternatively make the implementation calling the other one, or drag the one from namespace to global.

I tried to call in c++ to function from C file to my cpp file but getting some errors:

I have a
c++ project dll type .
I added/created to this project a new item/file called it ENCODER.c
In the ENCODER.c i have some functions like:
void init()
{
}
void start()
{
}
Now i added/created a new header file called it: ENCODER.h
In this one i did:
namespace Encode
{
class Encode
{
public:
static __declspec(dllexport) void init();
};
}
Then in the cpp file i did:
#include <stdexcept>
using namespace std;
#include "stdafx.h"
#include "targetver.h"
#include "ENCODER.h"
extern "C" {
void myinit()
{
Encode::Encode::init();
}
}
In the cpp file i want that
Encode::Encode::init(); this init()
will do/activate the init() function i have in the C file !!
Now after doing all that i'm getting two errors:
LNK2019: unresolved external symbol "public: static void __cdecl Encode::Encode::init(void)" (?init#Encode#1#SAXXZ) referenced in function _myinit
LNK1120: 1 unresolved externals
First you need to declspec(export) the whole class, but it's more complex than that as you need to declspec(import) when using the class. Use the following macro and define BUILDING_MYLIBRARY when building the library (and ensure it's undefined when using the library)
#ifdef BUILDING_MYLIBRARY
#define MYLIBRARY_EXPORT __declspec(export)
#else
#define MYLIBRARY_EXPORT __declspec(import)
#endif
And then use it like this:
class MYLIBRARY_EXPORT Encode
{
...
};
Next ensure that any C functions that can be seen by C++ are declared extern "C" to turn off name mangling (the technology C++ uses to allow function overloading). So create a header (ENCODER.h) file for the C functions as follows, and include the header file in any C++ implementation file that wishes to use these functions:
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
void MYLIBRARY_EXPORT init();
void MYLIBRARY_EXPORT start();
#ifdef __cplusplus
} // extern "C"
#endif
and then implement these functions in a separate implementation (ENCODER.c) file (the use of MYLIBRARY_EXPORT is optional; it depends if you want to expose them from your .dll). When implementing them you don't need the extern "C" or the MYLIBRARY_EXPORT as long as the compiler has seen the header file, so include it:
#include "ENCODER.h"
void init()
{
...
}
void start()
{
...
}
Suggestion: Choose better names! The start() function already exists in the C runtime library, so how about initEncoder() and startEncoder()?

Importing a C DLL's functions into a C++ program

I have a 3rd party library that's written in C. It exports all of its functions to a DLL.
I have the .h file, and I'm trying to load the DLL from my C++ program.
The first thing I tried was surrounding the parts where I #include the 3rd party lib in
#ifdef __cplusplus
extern "C" {
#endif
and, at the end
#ifdef __cplusplus
} // extern "C"
#endif
But the problem there was, all of the DLL file function linkage looked like this in their header files:
a_function = (void *)GetProcAddress(dll, "a_function");
While really a_function had type int (*a_function) (int *). Apparently MSVC++ compiler doesn't like this, while MSVC compiler does not seem to mind.
So I went through (brutal torture) and fixed them all to the pattern
typedef int (*_x_a_function) (int *); // using _a_function will not work, C uses it!
_x_a_function a_function ;
Then, to link it to the DLL code, in main():
a_function = (_x_a_function)GetProcAddress(dll, "a_function");
This SEEMS to make the compiler MUCH, MUCH happier, but it STILL complains with this final set of 143 errors, each saying for each of the DLL link attempts:
error LNK2005: _x_a_function already defined in main.obj main.obj
Multiple symbol definition errors.. sounds like a job for extern! SO I went and made ALL the function pointer declarations as follows:
function_pointers.h
typedef int (*_x_a_function) (int *);
extern _x_a_function a_function ;
And in a cpp file:
function_pointers.cpp
#include "function_pointers.h"
_x_a_function a_function ;
ALL fine and dandy.. except for linker errors now of the form:
error LNK2001: unresolved external symbol _a_function main.obj
Main.cpp includes "function_pointers.h", so it should know where to find each of the functions..
I am bamboozled. Does any one have any pointers to get me functional? (Pardon the pun..)
Linker errors like that suggest you've defined all the functions in function_pointers.cpp, but forgotten to add it to the project/makefile.
Either that, or you've forgotten to "extern C" the functions in function_pointers.cpp too.
I believe that if you declared the typedefs and/or the prototype as extern "C", you must remember to extern "C" the definition too.
When you link C functions the prototypes will get a leading _ in front of them by default so
when you do a typedef using the same name
typedef int (*_a_function) (int *);
_a_function a_function
you'll get issues because there is already a function in the dll named _a_function.
Usually you declare a function in yourlibrary.h like extern "C" __declspec(dllexport) int __cdecl factorial(int); then create that function in yourlibrary.c:
extern "C" __declspec(dllexport) int __cdecl factorial(int x) {
if(x == 0)
return 1;
else
return x * factorial(x - 1);
}
After compiling your DLL you get your .dll and .lib files. The latter is used when you want to import your functions to the project. You put #include "yourlibrary.h" and #pragma comment(lib, "yourlibrary.lib") in your project, after this you can use int factorial(int) in you application.