Function name is not decorated - dllexport

I am building a DLL which is having static reference to a library (.lib). Both the DLL and .lib has a function with same name but with different signature. I want to export the function written for the DLL. I am using .def file for exporting the function.
However, When I use dumpbin to export the function from the DLL, I dont see the decorated name for this function (having two function of the same name), for all other function I do see decorated name.
Function in A.cpp (DllName - ADLL)
uint __stdcall func(MSIHANDLE hHandle)
uint __stdcall func1(MSIHANDLE hHandle)
Function in .lib (B.lib) which is statically referenced in ADLL
DWORD WINAPI func(__in const bool input);
Format of def (ADLL.def) file :
LIBRARY "ADLL"
EXPORTS
func
func1
Snippet from .vcxProj
<ItemDefinitionGroup>
<Link>
<ModuleDefinitionFile>ADLL.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
Output from Dumpbin /Exports
ordinal hint RVA name
2 0 00035560 func = func
1 1 00001370 func1 = #ILT+875(?func1##YAIK#Z)
I am not able to understand why the function "func" doesn't have a decorated name like func1?

Related

What is the "address" being returned from GetProcAddress()?

I'm a little bit confused with GetProcAddress().
Quoting the Win32 docs:
If the function succeeds, the return value is the address of the exported function or variable.
I know that for functions, GetProcAddress() returns a function pointer that calls the desired function. However, it isn't clear what GetProcAddress() returns in something like this:
DLL code
typedef struct {
uint64_t foo;
double bar;
char* baz;
} MyStruct;
__declspec(dllexport) MyStruct* my_struct_ptr;
__declspec(dllexport) long long special_global;
Application code
void* my_struct_ptr = GetProcAddress(my_dll_handle, "my_struct_ptr");
void* special_global = GetProcAddress(my_dll_handle, "special_global");
What would my_struct_ptr and special_global in the application point to?
EDIT: Does my_struct_ptr point to the DLL's my_struct_ptr or the struct that the DLL's my_struct_ptr points to?

c++ unmanaged dll used by dllimport in C# produces entry point not found error

I know this question has been asked here many times before. I've read all those questions that I can find along with information outside of stackoverflow. So far I haven't found an answer i can figure out that will solve the specific problem that I'm having.
here is the code for the unmanaged c++ dll header file.
namespace MyWin32DLL
{
class MyWin32ClassOne
{
public:
static __declspec(dllexport) int Getvar();
};
}
Here is the code for the c++ dll cpp file
#include "MyWin32ClassOne.h"
namespace MyWin32DLL
{
int MyWin32ClassOne::Getvar()
{
return 123;
}
}
This code i've put together from various sources so it may not be right at all. I'm not very experienced with c++ or dll's.
Here is the code from my silly little c# winforms prog that I attempt to access the dll with. (edited to correct type mismatch as pointed out by tolanj in the comments)
namespace TestDll
{
public partial class Form1 : Form
{
[DllImport("MyWin32CppDll.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int Getvar();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string response = Getvar().ToString();
MessageBox.Show(response, "title", MessageBoxButtons.OK);
}
}
}
Now, at this point i understand that i'm probalby getting the "no entry point" error because of how the c++ compiler mangles the names of methods and functions.
From what i've read there are two things I can do to solve the problem.
Thing 1
Add extern "c" before my declaration so the name doesn't get mangled by the compiler.
namespace MyWin32DLL
{
class MyWin32ClassOne
{
public:
extern "C" static __declspec(dllexport) int Getvar();
};
}
When i try this I get an error from Visual Studio stating that "linkage specification isn't allowed".
Ok, so I try thing 2 which is to use dumpbin to find the mangled name of my function and use the mangled name as the entry point in the dllimport call.
So i run dumpbin /symbols on my dll and i get no function name, mangled or otherwise.
Dump of file mywin32cppdll.dll
File Type: DLL
Summary
1000 .data
1000 .idata
2000 .rdata
1000 .reloc
1000 .rsrc
4000 .text
10000 .textbss
Next i try dumpbin /exports
Dump of file mywin32cppdll.dll
File Type: DLL
Section contains the following exports for MyWin32CppDll.dll
00000000 characteristics
554CF7D4 time date stamp Fri May 08 13:52:20 2015
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00011005 ?Getvar#MyWin32ClassOne#MyWin32DLL##SAHXZ = #ILT+0(?Getvar#MyWin32ClassOne#MyWin32DLL##SAHXZ)
Summary
1000 .data
1000 .idata
2000 .rdata
1000 .reloc
1000 .rsrc
4000 .text
10000 .textbss
Looking at that I don't see a mangled or decorated name to use. But as a larth i use "Getvar#MyWin32ClassOne#MyWin32DLL##SAHXZ" as my entry point and still get the same error in my c# program.
Obviously I've missed something. How do I access the dll function from my c# program?
The name has been mangled, as you have observed. You've managed to omit the ? at the beginning of the mangled name. Your import should be:
[DllImport("MyWin32CppDll.dll", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?Getvar#MyWin32ClassOne#MyWin32DLL##SAHXZ")]
public static extern int Getvar();
Do note also that your function uses the cdecl calling convention.

__stdcall without any decoration

I have a .dll I suspect uses __stdcall functions, but totally undecorated names (not even an underscore or # sign). I wrote a .def file for it with aliases like
func1 = func1
func1#4 = func1
but I think lib (which I am using to create the import library from the .def file) is ignoring the aliases (the linker still says func1#4 is undefined)
How can I create an import library that will map func1#4 to func1?
I don't know if it possible to create right .lib file with lib.exe, so I suggest to create a DLL with stubs of functions exported by original DLL.
Example dll.cpp file:
void __stdcall foo(int) {}
dll.def file:
EXPORTS
foo=foo
Then you compile it, from IDE, or command line:
cl dll.cpp /link /dll /def:dll.def /noentry
It will create correct dll.lib file, so you can use it with code like this:
void __stdcall foo(int);
#pragma comment(lib, "dll")
int main()
{
foo(42);
}
You should be declaring the function prototype as extern "C" as you are (obviously) compiling with in C++ mode:
extern "C" void func1(void); // correct prototype, add __stdcall if necessary?
You can wrap entire sections of a header file inside
extern "C" {
// ... C compatible declarations
}

Visual Studio, MSBuild: First build after a clean fails, following builds succeed

There's obviously something wrong with my build, but I can't figure it out. I narrowed this down to one of my projects: first build after clean fails, all following builds succeed.
I get linking errors which say that some symbols are already defined:
>------ Build started: Project: Problem, Configuration: Debug Win32 ------
> Blah blah blah...
23> Creating library D:\SVN.DRA.WorkingCopy\Debug\Problem.lib and object D:\SVN.DRA.WorkingCopy\Debug\Problem.exp
23>ProblemDependency1.lib(PD1.obj) : error LNK2005: "public: unsigned short __thiscall PD2Class::getFoo(void)const " (?getFoo#PD2Class##QBEGXZ) already defined in ProblemDependecy2.lib(ProblemDependency2.dll)
23>ProblemDependency1.lib(PD1.obj) : error LNK2005: "public: void __thiscall PD2Class2::`default constructor closure'(void)" (??_FPD2Class2#Image#DRA##QAEXXZ) already defined in ProblemDependency2.lib(ProblemDependency2.dll)
23>D:\SVN.DRA.WorkingCopy\Debug\Problem.dll : fatal error LNK1169: one or more multiply defined symbols found
Problem is a C++/CLI project, built with the /clr switch, which references the unmanaged C++ projects ProblemDependency1, a static lib, and ProblemDependency2, a dll.
ProblemDependency1 references ProblemDependency2.
getFoo() is declared as inline and defined outside of the class declaration, in the .h
PD2Class2 doesn't have an explicitly defined default constructor, but it has a constructor which has all default arguments, so you could say it includes the default constructor as a special case
The .h's where these are defined have #pragma once as their first line.
Any hint on troubleshooting this? I can post more info if needed
Update: I solved the first error thanks to Anders Abel's suggestion, but I still can't solve the second one (the one about the default constructor)
Update: If I compile using MSBuild outside Visual Studio, it fails always, with the same error
Edit: Here's some code. First, a bit of PD2Class2's declaration. PD2Class2's real name is CImage (feeling lazy to anonymize), CImage.h:
#pragma once
#pragma warning( disable: 4251 ) //TODO: Disable and solve
#include "ImageProperties.h"
#include "../CommonCppLibrary/CriticalSection.h"
#include <windows.h>
#include <stdexcept>
#include <string>
class CSharedMemory;
class EmptyImageException;
struct IShape;
struct SImageStatics {
unsigned short low3Percentile;
unsigned short high97Percentile;
unsigned short medianPixelValue;
unsigned short meanPixelValue;
unsigned short minPixelValue;
unsigned short maxPixelValue;
};
namespace DRA{
namespace Image{
class __declspec(dllexport) CImage {
friend class CImageLock;
//Attributes
int m_iPitch;
protected:
mutable CImageProperties m_cProperties;
CSharedMemory * m_pSharedMemmory;
mutable DRA::CommonCpp::CCriticalSection m_csData;
static const float PIXEL_FREQUENCY_COVERAGE;
static const float PIXEL_CUTOFF_PERCENTAGE;
static const int MINIMUM_PIXEL_FREQUENCY; //Pixels with a frequency lower than this are ignored
static const int MINIMUM_WINDOW_WIDTH_FOR_16_BITS;
//Methods
//Some private methods
public:
CImage( DWORD dwWidth = 0, DWORD dwHeight = 0, ULONG uBytesPerPixel = 0,
bool isSigned = false, EPhotometricInterpretation ePI = PI_UNKNOWN,
UINT bitsStored = 0, float pw = -1.0f, float ph = -1.0f, BYTE * pData = NULL );
CImage( const CImageProperties& cProperties, int iPitch = 0 );
CImage( const CImage& rImage );
virtual ~CImage();
virtual CImage& operator=( const CImage& );
bool operator==( const CImage& rImage );
//Alter State
//More methods
//Query State
//More methods
};
}
}
Next, the constructor's definition, from CImage.cpp:
CImage::CImage( DWORD dwWidth, DWORD dwHeight, ULONG uBytesPerPixel, bool isSigned,
EPhotometricInterpretation ePI, UINT bitsStored, float pw, float ph,
BYTE * pData ) :
m_iPitch( dwWidth * uBytesPerPixel ),
m_cProperties( dwWidth, dwHeight, uBytesPerPixel, bitsStored, ePI, isSigned, pw, ph ),
m_pSharedMemmory( NULL ),
m_csData(){
m_pSharedMemmory = new CSharedMemory( pData ? pData : new BYTE[getSize()] );
}
Is getFoo() marked as __declspec(dllexport)? If it is an inline function, it is instantiated/used from wherever it is called through the included header. It shouldn't be part of the functions that the dll exports and it should not have a dllexport directive.
__declspec(dllexport) might be handled through a macro that is expanded to dllexport or dllimport depending on if it is the dll or code using the dll that is compiled. If there is any macro in the function declaration you might have to dig into it to find if there is an export directive.
Update
I think that if the header file is used both when the dll is built and when the dll is used, it is incorrect to have __declspec(dllexport) in the header file. Instead use a macro system:
#ifdef PROBLEMDEPENDENCY2
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT CImage
{
//...
}
Then define the PROBLEMDEPENDENCY2 preprocessor symbol when building the dll, but not when using it. The problem with hardcoding __declspec(dllexport) in the header file is that the compiler will try to export the class both from ProblemDependency2 (which is correct) and from ProblemDependency1 (which is incorrect).
Just something I've run into recently to check:
Are you building on a network volume? I had been having problems with not being able to debug my applications because the .pdb file was not "there" after the build and before the debug launch due to latency in the SAN that I was working on as a build directory.
Once I moved the project build to a local volume, everything was fine.
Don't know if that's what's happening to you or not, but something I'd look into.
I dont' have much c++ experience, but problems like this in other .NET languages, often result from having a DLL reference to another project in the same solution (to the DLL in the "obj" or "bin" folder of the other project, instead of a project reference. This stops Visual Studio from being able to figure out the build order, and, hence, the first time after a "clean", you will not have the DLL you are depending on. On the second build, this DLL will already have been built, and the build will succeed.

Difference between Linux and Windows linker

What is the difference in linking on various operating system?
For example the following code produces a linker error on Windows (compiled both with Vs2010 and gcc), but compiles successfully on Linux (Ubuntu,gcc):
extern int foo
int main() {
foo=1;
}
Gcc command:
gcc -shared filename.cpp
If you are trying to compile it as a windows shared library you need something like (code stolen from Wikipedia!) :-
#include <windows.h>
// DLL entry function (called on load, unload, ...)
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}
// Exported function - adds two numbers
extern "C" __declspec(dllexport) double AddNumbers(double a, double b)
{
return a + b;
}
Windows shared modules (DLLs) require a DllMain entry point (executed the first time the module is loaded) and function names need to be exported via the declspec gobledygook before they can be used by another program.

Resources