c++ dll function export naming conventions (mangling) - c++

I am totally new in C++ and starting with creating a simple dll and console app that tests the dll. The dll plugin afterwards should work on x86 machines (diag tools, ECU or PLC). The samples given to me that I fallow the same structure exports dll function as __sdcall. so my helloWorld project looks like:
plugin.dll
-----------
plugin.h
#pragma once
#include "types.h"
#define EXPORT extern "C" __declspec (dllexport)
EXPORT S32 WINAPI Greetings(string *str);
plugin.cpp
#include "plugin.h"
#include "types.h"
S32 __stdcall Greetings(string *str){*str = "Hello From Plugin!"; return -1;}
and the console app looks like: (both are in same solution, project/properties/cc++/adnvances/callingConvention = __cdecl (/Gd))
VS settings - Solution configuration=debug, Solution Platforms=x86
main.cpp
HMODULE DllHandler = ::LoadLibrary(L"plugin.dll");
string greetingText;
typedef U32(*Type)(string*);
Type greetings = reinterpret_cast<Type>(GetProcAddress(DllHandler, "Greetings"));
greetings(&greetingText);
cout << greetingText << endl;
Now, without plugin.def the GetProcAddress(DllHandler, "Greetings") returns null (0x000000) with the plugin.def (alongside with EXPORT) I get the Greetings with decoration plugin.dll!Greetings#4 the call will succeed but get
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
also no casting with naming convention is allowed.
I red many posts about __cdecl __stdcall but mostly explaining the assembly level that who cleans the stack, or using either .def or extern "C" with export.
I totally got lost in naming convention and mangling in C++. is related to local project setting or the dll will run on all environments? specially in this sample project how should I handle it?

Related

Using a c++ builder application with an external dll

I'm trying to use an external dll in my c++ builder application. The dll (let.s call it X.dll) was created with Qt Creator (using MingW 32 bit compiler, tried gcc as well )
and consists of a single functon to keep things simple (besides X.dll, an import library X.a is also created).
The dll header (Dll_lib.h) is basically just
__declspec(dllexport) Dll_method(float *p, int n);
If I create a simple Qt application, add the dll header to it and link it to the dll import library X.a, everythink works as expected.
However, when I try to use the dll in my c++ builder application, I get an "unresolved external _Dll_method referenced from ..." error.
The part of my c++ builder app that references the dll looks like
#include "lib\Dll_lib.h"
#pragma comment(lib, "X.lib")
__declspec(dllimport) Dll_method(float *p, int n);
.....
X.lib was created directly from the dll using the implib tool that comes bundled with c++ builder. I also tried to create X.lib from X.a using coff2omf tool but nothing worked and I always get the same error message.
C++ environments have a habit of name mangling to support overloads, different arguments with the same name, like:
int use(int x, char y); // mangles to something like use__Int__Chr.
int use(double x); // mangles to something like use__Dbl.
This allows the correct one to be linked depending on the arguments.
You may need to wrap it inside extern "C" to get it to not mangle the name, something like:
extern "C" {
__declspec(dllimport) Dll_method(float *p, int n);
}
That's assuming you're creating it without name mangling and using it from something that assumes it is mangled. If it's mangled on both sides, you'll probably have to create and use it with extern "C" since there's no guarantee different compilers will mangle with the same rules.
As an aside, you should be able to examine the object files or DLLs created by your toolchain, to ascertain what the function is called where it's defined and also what it's expected to be by the caller. Under Linux, I'd use something like nm, I'm not sure what the equivalent is for Windows.

Standard method for creating dll in c++ and calling in delphi

I am looking for the correct method to create a DLL in C++ and call it in Delphi. I use CodeBlocks for the DLL and Delphi RAD Studio 10.2.
My C++ header and source code for building the DLL as described in How to create dll in C++ for using in C# is as follows:
Main.h:
#ifndef MATH_HPP
#define MATH_HPP
extern "C"
{
__declspec(dllexport) int __stdcall math_add(int a, int b);
}
#endif
Main.Cpp :
#include "main.h"
int __declspec(dllexport) __stdcall math_add(int a, int b)
{
return a + b;
}
This code in CodeBlocks builds math_dll.dll without any error.
Calling the DLL in Delphi:
function math_add(X, Y: Integer): Integer; stdcall; external 'math_dll.dll' name 'math_add';
But when I run Delphi and call this function, I have the following error:
"the procedure entry point math_add could not be located in the dynamic link library math_dll.dll"
Which part of my code is wrong?
The default name mangling for the __stdcall calling convention is _<name>#<bytes_in_arguments>. So your DLL function is most likely being exported as '_math_add#8' instead of as 'math_add' like you are expecting. Use a tool like PEDUMP to verify that.
You can use a .DEF file when compiling the DLL to change the exported name, or you can update your Delphi function declaration to use the correct exported name for the name attribute.

Using C++ app in .NET

I am new to using PInvoke with Classic C++ and I asked this question yesterday: Using Windows API functions in .NET
I have now created a very simple C++ program as follows:
#include <iostream>
#include <stdio.h>
#include <string>
extern "C" __declspec(dllexport) int hello()
{
//printf ("Hello World!\n");
return 1;
}
I then compiled the DLL using the following command: g++ -c mydll.cpp
Then created the shared library using the following command: g++ -shared -o mydll.dll mydll.o, then copied mydll.dll to C:\Windows\syswow64.
I then created a new VB.NET project and created the following code:
Imports System.Runtime.InteropServices
Public Class TestPlatformInvoke
<DllImport("mydll.dll", CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Function hello() As Integer
End Function
Public Sub New()
Try
Dim test As Integer = hello() 'Line 6 ex As Exception
'I don't swallow exceptions
MsgBox("test")
Catch ex As Exception
End Try
End Sub
End Class
The application exits after calling hello(). It does not throw an exception.
I am trying to get to grips with how this works. I don't have any commercial experience with c++; only academic experience at university.
Here is an image of Dependancy Walker for mydll.dll.
Declare is VB6 legacy. You should use p/invoke and the DllImport attribute.
<DllImport("mydll.dll", CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Function hello() As Integer
End Function
There are lots of ways that this could fail. Perhaps the DLL is not loading because there's a 32/64 bit mismatch. Also, your calling conventions do not match. Your DLL will be using cdecl but your VB code uses stdcall. The pinvoke above fixes that.
Most seriously your function does not appear to have been exported from the DLL. That's going to make it fail for sure. Use Dependency Walker to determined whether or not your function has been exported. I'm not so familiar with g++ so you'll have to work out how to export your function using the GNU toolchain. But watch out for name decoration and name mangling. You may need to take care with how you export your function so that it is exported with the desired name.
If you use Visual Studio to debug programs and include the DLL in your project (Visual Studio 2012 Express Edition allows including projects of different types in the solution), you may set the "Allow native code debugging" option to automatically switch the debugger from the VB.NET to C++, when you P/Invoke function from the DLL.
Here's a working Proof-of-concept. Simply unzip, open in Visual Studio, build and run. You may compare this program with your project and find the differences, which makes your code failing.
I guess, that you haven't actually exported the function from the DLL. Simply including it in the DLL's code may not be enough: check, which functions are exported from the DLL using the Dependency Walker (other link) program. For example, I had to add folowing declaration:
__declspec(dllexport) int __stdcall Test() { ... }
And additionally create the .def file for the names for exported functions not to be decorated.
Try to modify your DLL source code and change the function declaration to:
extern "C" __declspec(dllexport) int hello()
{
return 1;
}

making an VC++ .exe to DLL .is it possible?

I have an VC++ win 32 application which compiles into an EXE. But now I want to convert it into dll so that I can load that in another application.I tried changing in Visual Studio properties from .EXE to .DLL which successfully converted it but whn i use GetProcAddress it always returns NULL . I am not sure what I am doing is right or wrong .
Basically this what I want to achieve :
I want to link project 1 and project2
Project 2 should be able to invoke the functions of project1(which is an exe currenlty)
EDIT
Hi guys thanks for your input .I told what you guys said . even then my GetProcAddress returns zero . Am i am doing anything wrong .Shown my dll loading code below .
HINSTANCE LoadMe = LoadLibrary( _T("D:\\VC++Project\\CVAList\\CVAList\\ExportTest.dll"));
if (LoadMe != 0)
printf("LoadMe library loaded!\n");
else
printf("LoadMe library failed to load!\n");
EntryPointfuncPtr LibMainEntryPoint;
LibMainEntryPoint = (EntryPointfuncPtr)GetProcAddress(LoadMe,"PrintFloatsVal");
LibMainEntryPoint (a1 ,a,b,c,d ); // 4 double
EDIT DLL Export Code
#define DllExport __declspec( dllexport )
DllExport void PrintFloatsVal ( int amount, double &d1 ,double &d2 , double &d3 ,double &d4)
{
....
..
}
You need to export the functions you wish to access using the __declspec dllexport keyword.
So if you add the manifest constant 'BUILDING_MY_DLL' to the project, the header file that declares the functions you care about can be used in both the DLL project and any code that uses the DLL:
#ifdef BUILDING_MY_DLL
#define MY_DLL_EXPORT __declspec dllexport
#else
#define MY_DLL_EXPORT __declspec dllimport
#endif
And decorate the functions you wish to export:
MY_DLL_EXPORT BOOL Func1(int a);
If the function you wish to access is implemented in C++ it will be decorated, for the purposes of function overloading and other purposes, and it best accessed directly like any other function. If you wish to use GetProcAddress() however you are better off giving it C-linkage by surrounding the function with extern "C" { ... }. This will make the exported name the same the name used within the code.
Reference: http://msdn.microsoft.com/en-us/library/a90k134d(v=vs.80).aspx

Compile a DLL in C/C++, then call it from another program

I want to make a simple, simple DLL which exports one or two functions, then try to call it from another program... Everywhere I've looked so far, is for complicated matters, different ways of linking things together, weird problems that I haven't even begun to realize exist yet... I just want to get started, by doing something like so:
Make a DLL which exports some functions, like,
int add2(int num){
return num + 2;
}
int mult(int num1, int num2){
int product;
product = num1 * num2;
return product;
}
I'm compiling with MinGW, I'd like to do this in C, but if there's any real differences doing it in C++, I'd like to know those also. I want to know how to load that DLL into another C (and C++) program, and then call those functions from it.
My goal here, after playing around with DLLs for a bit, is to make a VB front-end for C(++) code, by loading DLLs into visual basic (I have visual studio 6, I just want to make some forms and events for the objects on those forms, which call the DLL).
I need to know how to call gcc (/g++) to make it create a DLL, but also how to write (/generate) an exports file... and what I can/cannot do in a DLL (like, can I take arguments by pointer/reference from the VB front-end? Can the DLL call a theoretical function in the front-end? Or have a function take a "function pointer" (I don't even know if that's possible) from VB and call it?) I'm fairly certain I can't pass a variant to the DLL...but that's all I know really.
update again
Okay, I figured out how to compile it with gcc, to make the dll I ran
gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--out-implib,libmessage.a
and then I had another program load it and test the functions, and it worked great,
thanks so much for the advice,
but I tried loading it with VB6, like this
Public Declare Function add2 Lib "C:\c\dll\mydll.dll" (num As Integer) As Integer
then I just called add2(text1.text) from a form, but it gave me a runtime error:
"Can't find DLL entry point add2 in C:\c\dll\mydll.dll"
this is the code I compiled for the DLL:
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
EXPORT int __stdcall add2(int num){
return num + 2;
}
EXPORT int __stdcall mul(int num1, int num2){
return num1 * num2;
}
calling it from the C program like this worked, though:
#include<stdio.h>
#include<windows.h>
int main(){
HANDLE ldll;
int (*add2)(int);
int (*mul)(int,int);
ldll = LoadLibrary("mydll.dll");
if(ldll>(void*)HINSTANCE_ERROR){
add2 = GetProcAddress(ldll, "add2");
mul = GetProcAddress(ldll, "mul");
printf("add2(3): %d\nmul(4,5): %d", add2(3), mul(4,5));
} else {
printf("ERROR.");
}
}
any ideas?
solved it
To solve the previous problem, I just had to compile it like so:
gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--add-stdcall-alias
and use this API call in VB6
Public Declare Function add2 Lib "C:\c\dll\mydll" _
(ByVal num As Integer) As Integer
I learned not to forget to specify ByVal or ByRef explicitly--I was just getting back the address of the argument I passed, it looked like, -3048.
Regarding building a DLL using MinGW, here are some very brief instructions.
First, you need to mark your functions for export, so they can be used by callers of the DLL. To do this, modify them so they look like (for example)
__declspec( dllexport ) int add2(int num){
return num + 2;
}
then, assuming your functions are in a file called funcs.c, you can compile them:
gcc -shared -o mylib.dll funcs.c
The -shared flag tells gcc to create a DLL.
To check if the DLL has actually exported the functions, get hold of the free Dependency Walker tool and use it to examine the DLL.
For a free IDE which will automate all the flags etc. needed to build DLLs, take a look at the excellent Code::Blocks, which works very well with MinGW.
Edit: For more details on this subject, see the article Creating a MinGW DLL for Use with Visual Basic on the MinGW Wiki.
Here is how you do it:
In .h
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
extern "C" // Only if you are using C++ rather than C
{
EXPORT int __stdcall add2(int num);
EXPORT int __stdcall mult(int num1, int num2);
}
in .cpp
extern "C" // Only if you are using C++ rather than C
{
EXPORT int __stdcall add2(int num)
{
return num + 2;
}
EXPORT int __stdcall mult(int num1, int num2)
{
int product;
product = num1 * num2;
return product;
}
}
The macro tells your module (i.e your .cpp files) that they are providing the dll stuff to the outside world. People who incude your .h file want to import the same functions, so they sell EXPORT as telling the linker to import. You need to add BUILD_DLL to the project compile options, and you might want to rename it to something obviously specific to your project (in case a dll uses your dll).
You might also need to create a .def file to rename the functions and de-obfuscate the names (C/C++ mangles those names). This blog entry might be an interesting launching off point about that.
Loading your own custom dlls is just like loading system dlls. Just ensure that the DLL is on your system path. C:\windows\ or the working dir of your application are an easy place to put your dll.
There is but one difference. You have to take care or name mangling win C++. But on windows you have to take care about
1) decrating the functions to be exported from the DLL
2) write a so called .def file which lists all the exported symbols.
In Windows while compiling a DLL have have to use
__declspec(dllexport)
but while using it you have to write
__declspec(dllimport)
So the usual way of doing that is something like
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
The naming is a bit confusing, because it is often named EXPORT.. But that's what you'll find in most of the headers somwhere. So in your case you'd write (with the above #define)
int DLL_EXPORT add....
int DLL_EXPORT mult...
Remember that you have to add the Preprocessor directive BUILD_DLL during building the shared library.
Regards
Friedrich
The thing to watch out for when writing C++ dlls is name mangling. If you want interoperability between C and C++, you'd be better off by exporting non-mangled C-style functions from within the dll.
You have two options to use a dll
Either use a lib file to link the symbols -- compile time dynamic linking
Use LoadLibrary() or some suitable function to load the library, retrieve a function pointer (GetProcAddress) and call it -- runtime dynamic linking
Exporting classes will not work if you follow the second method though.
For VB6:
You need to declare your C functions as __stdcall, otherwise you get "invalid calling convention" type errors. About other your questions:
can I take arguments by pointer/reference from the VB front-end?
Yes, use ByRef/ByVal modifiers.
Can the DLL call a theoretical function in the front-end?
Yes, use AddressOf statement. You need to pass function pointer to dll before.
Or have a function take a "function pointer" (I don't even know if that's possible) from VB and call it?)
Yes, use AddressOf statement.
update (more questions appeared :)):
to load it into VB, do I just do the usual method (what I would do to load winsock.ocx or some other runtime, but find my DLL instead) or do I put an API call into a module?
You need to decaler API function in VB6 code, like next:
Private Declare Function SHGetSpecialFolderLocation Lib "shell32" _
(ByVal hwndOwner As Long, _
ByVal nFolder As Long, _
ByRef pidl As Long) As Long