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:
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:
I found that, for situation a1, I couldn't simply use the following C# source code to load the function:
The exception would be like:
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:
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:
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:
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:
The investigation shows good result.
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.
相关文章推荐
- C++ (P70—P96)
- C++中new与malloc的10点区别
- C++中的虚函数(virtual function)
- 对于C++ Builder 使用DevPress 控件中的TCXGrid 添加复选框 在勾选时会闪退
- delete与delete[]
- C++在类内定义模板函数
- C++ primer 第五版 中文版 练习 12.20
- C,C++宏中#与##的讲解
- C++中#include<iostream.h>和#include<iostream>
- MyString类的实现--C++ primer plus 读书笔记
- C++MFC编程笔记day01 MFC介绍、创建MFC程序和重写消息处理
- C++学习方法
- C/C++字符串
- C++中的单例模式
- 声明已被否决 VS C++
- C语言编码与字符转换
- C++单例
- C++基础总结(4)-----指针
- C++成员变量初始化顺序问题
- C++基础总结(4)-----指针