您的位置:首页 > 编程语言 > C语言/C++

Exporting a function in a DLL using Microsoft Visual C++ 6.0

2016-03-03 11:11 561 查看
Background

There is a function written in C (not necessarily in C++). The function is a part of the source code of a DLL, namely PreciseLanczosDLL.dll. There is a C# program, namely PreciseLanczosSharp, which wants to consume the function in the DLL.

Requirement

The function needs to be exported in a form in which the C# program can access it. In addition, the exported function name should be easy to understand.

Investigation and result

I tried the following two ways:

a1. Using a __declspec(dllexport) declaration in the header file.

a2. Using a .DEF file.

In the C# project, I added a copy command to the pre-build steps to copy the dll file to the target directory of the C# file:

copy $(ProjectDir)..\PreciseLanczosDLL\Release\PreciseLanczosDLL.dll $(ProjectDir)$(OutDir)


This way, each time the project is rebuilt, the dll file is automatically copied and can be used.

I simply used the following declaration in the header file to export the function from the dll:

__declspec(dllexport) int WINAPI fnPreciseLanczosDLL(void);


I found that, for situation a1, I couldn't simply use the following C# source code to load the function:

[DllImport("PreciseLanczosDLL.dll", CallingConvention=CallingConvention.StdCall,
SetLastError=false)]
public static extern int fnPreciseLanczosDLL();


The exception would be like:

Unhandled Exception: System.EntryPointNotFoundException: Unable to find an entry
point named 'fnPreciseLanczosDLL' in DLL 'PreciseLanczosDLL.dll'.


What tool can I use to look into the generated dll? I found Dependency Walker. I then then used Dependency Walker (version 2.2) to look at the dll as the compilation result. I found that the exported function is not called "fnPreciseLanczosDLL". Instead, it's
called "?nPreciseLanczosDLL@@3HA".

I think that the function name might have been mangled for use with C++. As we all know, C++ allows function overloading while C doesn't. To allow function overloading, a function with the same name can have multiple declarations and implementations based on
the signature, which consists of both the function name and the list of parameter types. When exporting such a function to a dll or to a debugger, it must be mangled so that each function declaration has its own mangled name.

Then I tried forcing Visual C++ compiler not to mangle the name. I successfully did that, by using the following lines of code in the header file:

extern "C" {
__declspec(dllexport) int WINAPI fnPreciseLanczosDLL(void);
}


However, as Dependency Walker shows it, the unmangled name in the DLL is "_fnPreciseLanczosDLL@0", rather than "fnPreciseLanczosDLL".

When I import the function in the C# program, I have to use the following source code:

[DllImport("PreciseLanczosDLL.dll", CallingConvention=CallingConvention.StdCall,
SetLastError=false, EntryPoint="_fnPreciseLanczosDLL@0")]
public static extern int fnPreciseLanczosDLL();


This is ugly. So I tried method a2. I used a .DEF file, and commented out the __declspec(dllexport) line in the header file (later I found that leaving the __declspec(dllexport) line in the file is still OK--it just won't have any effect). The .DEF file looks
like:

LIBRARY PreciseLanczosDLL
DESCRIPTION "PreciseLanczos Library"
EXPORTS
fnPreciseLanczosDLL @1


Now, Dependency Walker shows the expected exporting name: fnPreciseLanczosDLL. Its ordinal is 1 but this is not a part of the function name. Now the C# code is also clean:

[DllImport("PreciseLanczosDLL.dll", CallingConvention=CallingConvention.StdCall,
SetLastError=false)]
public static extern int fnPreciseLanczosDLL();


The investigation shows good result.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: