DLL not exporting function properly

I'm a little confused because I have tried using both a .def file to export a function, and I have tried __declspec(dllexport) to export the function, and even both at once. With using the .def file the function cannot be found inside the DLL from any text editor, whereas using the declspec method is can be, but neither method allows an external application to find the DLL (the external app is not mine and it works for other DLLs just fine). I have uploaded my project here if you need to fully look at it:
http://www.LB-Stuff.com/C++/DLL_Test.zip

I am at a total loss here as I have followed exactly tutorials for Visual C++ 2008 Express Edition and it is still not working. What am I doing wrong?
Have you gone into project properties linker options and told Visual Studio to link against the *.lib file?
Is that the "Link Library Dependencies" field? It was already set to Yes.
I haven't used def files before but why is there a semi-colon in it? The examples I've seen on the net don't have any. Also, according to MSDN, 0 is not a valid ordinal number. I think it should be 1 instead.

More likely though, the problem you're having is due to name mangling. When I ran Dependency Walker on Release/DLL_Test.dll, it found the function:

?TestFunc@@YAHHH@Z

If I understand correctly, the .def file exports should contain the fully-mangled function name. If you use C linkage (Extern "C") around TestFunc, then your def file will probably work.
The semi-colon is a comment because I wanted to comment out that line to try and test the declspec method alone.

Also, I'm using an SDK for DLLs where the .def file works fine with the functions *without* being wrapped in extern "C", and I would still like to use C++ features in functions. I'll do some more testing and see if I can figure out how the SDK works and the properties and such.
but neither method allows an external application to find the DLL (the external app is not mine and it works for other DLLs just fine)


I don't know what to say to this because I created a VS 2005 project, linked with Final/DLL_Test.lib, put Final/DLL_Test.dll in my exe's directory, and it worked.

I did however have to create a separate .h file with this in it:

1
2
3
4
5
6
7
//DLL_Test.h
#ifndef __DLL_TEST_H
#define __DLL_TEST_H

__declspec(dllimport) int TestFunc(int a, int b);

#endif 


so that my project knew that TestFunc would be in the dll. But yeah, besides that, it worked.
I think I found the issue, your function is being exported by the name "?TestFunc@@YAHHH@Z". I took the long way around in calling your function on windows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

#include <windows.h>

void pause()
{
    std::cin.sync();
    std::cin.ignore();
}


int main( int argc, char* args[] )
{
    
    HMODULE Lib = LoadLibrary("C:\\Program Files\\Dev-Cpp\\New Folder\\Output\\MingW\\DLL_Test.dll");
    if(Lib == NULL)
        {
            MessageBox(NULL, "Error Loading DLL", "ERROR", MB_OK);
            std::cout << GetLastError();
            pause();
            return 1;
        }
    
    
    
    HMODULE DLL = GetModuleHandle("C:\\Program Files\\Dev-Cpp\\New Folder\\Output\\MingW\\DLL_Test.dll");
    if(DLL == NULL)
        {
            MessageBox(NULL, "Error Getting DLL", "ERROR", MB_OK);
            std::cout << GetLastError();
            pause();
            return 2;
        }
    
    int (*Addr)(int, int) = (int (*)(int, int)) GetProcAddress(DLL, "?TestFunc@@YAHHH@Z");
    if(Addr == NULL)
        {
            MessageBox(NULL, "Error Getting Function Address", "ERROR", MB_OK);
            std::cout << GetLastError();
            pause();
            return 3;
        }
    
    std::cout << Addr(2,4);
    
    pause();
    return 0;
}

I'm using wxDev-C++ by the way, don't be fooled by the directory names.

EDIT: Here's a tool that will help spot annoying stuff like this: http://www.nirsoft.net/utils/dll_export_viewer.html
Last edited on
I think I found the issue, your function is being exported by the name "?TestFunc@@YAHHH@Z"

I found this as well.

shacktar wrote:
More likely though, the problem you're having is due to name mangling. When I ran Dependency Walker on Release/DLL_Test.dll, it found the function:

?TestFunc@@YAHHH@Z

If I understand correctly, the .def file exports should contain the fully-mangled function name.


L B wrote:
I'm using an SDK for DLLs where the .def file works fine with the functions *without* being wrapped in extern "C"

Can you explain what you mean "SDK for DLLs"? Are you talking about some other .def file here? Because you said in your original post that you couldn't get your .def file to work.
Last edited on
I want to dynamically link the DLL (no use for *.lib whatsoever). For some other software I use I can develop addons/components and such by using an SDK that compiles to DLLs. All I have to do is plop the compiled DLL in a directory (no lib files) and the program dynamically loads it in with a bunch of others. I wanted to try and figure out how this worked, which is why I tried to make this test DLL.

I copied and pasted the same stuff from the .def file from the SDK and narrowed it to just my one function. However, when compiled, the function is not even included in the DLL and the DLL is 0.5 kb smaller. I can deal with the name obfuscation, but I want to know how to get around it the same way the SDK does it - the names in the compiled DLLs are not obfuscated at all.

Upon not using __declspec(dllexport) and uncommenting the line in the .def file in my test project here, the function, as far as I can tell, is not exported into the compiled DLL at all.
I copied and pasted the same stuff from the .def file from the SDK and narrowed it to just my one function. However, when compiled, the function is not even included in the DLL and the DLL is 0.5 kb smaller. I can deal with the name obfuscation, but I want to know how to get around it the same way the SDK does it - the names in the compiled DLLs are not obfuscated at all.

Try creating the following functions when using the SDK to compile to a DLL:

1
2
int testFunc(int a, int b);
int testFunc(int a, int b, int c);

I would be surprised if the DLL did not contain mangled names for both prototypes of testFunc. I suspect that the SDK checks to see if there aren't any overloads for a particular function, and if not, it applies C linkage to it. I also suspect that it leaves any symbols mangled if there's nothing it can do about it. AFAIK, to get rid of name mangling in the DLL, you need to use C linkage.

Also, another shot in the dark, but maybe this SDK is for C not C++? Maybe if it doesn't see any C++ specific stuff, it just uses C linkage? Have you tried compiling classes, using namespaces, and other C++ specifics when compiling with the SDK? Sorry I can't be more helpful :s
Last edited on
None of the functions in the SDK are overload (for that specific reason). And yes, it was written mostly with C-style coding but it works perfectly with C++ features like classes, templates, namespaces, etc. The SDK is in the form of a bunch of headers with a template .dsp project for VC++2005 which my VC++2008 converts into a .sln - I'm not really sure how it 'checks' for things, considering that the only functions I add to it are not exported but rather their address is given to the parent application.

So, how would I do this C linkage whilst still being able to use C++ features?
A function linked with C linkage can still use C++ features. As long as the function has no overloads, you're good to go.

e.g.

1
2
3
4
5
6
7
//DLL.h

//exported
extern "C"
{
     void CPlusPlusFunc();
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//DLL.cpp

#include <iostream>
#include <string>
#include <map>
using namespace std;

void CPlusPlusFunc()
{
     map<string, int> myMap;
     myMap["one"] = 1;
     myMap["two"] = 2;
     myMap["three"] = 3;

     for(myMap::iterator it = myMap.begin(); it != myMap.end(); it++)
     {
          cout<<"("<<it->first<<", "<<it->second<<")"<<endl;
     }
}


Don't know if this is relevant for your case, but, for exporting classes, you need to make two factory functions, one that instantiates the class and returns a void pointer, and another that takes in a void pointer and deletes the instance of the class.

e.g.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//DLL.h

//not exported
class myClass
{
   //...
};

//exported
extern "C"
{
     void* CreateMyClassInstance();
     void DestroyMyClassInstance(void *);
}


1
2
3
4
5
6
7
8
9
10
//DLL.cpp
void* CreateMyClassInstance()
{
     return new myClass;
}

void DestroyMyClassInstance(void* ptrMyClass)
{
     delete ptrMyClass;
}


The client code would have access to a .h file which shows an abstract version of "myClass" and the client code would only use instances of "myClass" through pointers.

I'm not really sure how it 'checks' for things, considering that the only functions I add to it are not exported but rather their address is given to the parent application.

I don't know how this SDK works, and I'm having a little trouble imagining it to be honest. I just assume it somehow knows to use C linkage silently.
Actually, I didn't have to do this at all. The problem was that I hadn't told the linker to use my .def file, so of course the function was never being exported. Now that I've told my linker to use the .def file it exports the function just fine with no name mangling ar any extern "C". If anyone else is interested, this is where I had to put the filename for the .def:
http://www.LB-Stuff.com/C++/DLL_export.png
Thanks for all the help...!
Topic archived. No new replies allowed.