关于dll的导出符号


函数原型:
	extern "C" __declspec(dllexport) int _stdcall GZipCompression(const char *, int , char *, int )
编译后的导出符号:
	_GZipCompression@16
	
	
函数原型:
	extern "C" __declspec(dllexport) int _cdecl GZipCompression(const char *, int , char *, int )
编译后的导出符号:
	GZipCompression

	
函数原型:
	__declspec(dllexport) int _cdecl GZipCompression(const char *, int , char *, int )
编译后的导出符号:
	?GZipCompression@@YAHPBDHPADH@Z

	
函数原型:
	__declspec(dllexport) int _stdcall GZipCompression(const char *, int , char *, int )
编译后的导出符号:
	?GZipCompression@@YGHPBDHPADH@Z


extern "C" 按照c的方式进行符号修饰
{
c方式下的两种调用惯例所产生的符号
_cdecl 不产生任何修饰
_stdcall 下划线 + 函数原型名称 + @ + 参数的字节总和
}

c++方式进行的符号修饰相对复杂
{
...
}

::LoadLibrary(LPCTSTR szDLL)的返回值 既为对应DLL在进程虚拟地址空间中的虚拟地址
首个自定义被加载的dll 对应的地址应为0x10000000
而系统相关的dll 应该在进程加载前就已经位于内存中 且相应的代码为系统代码 应该处于进程地址空间中的高地址空间内


::GetProcAddress() 中所制定的符号 对应为dll的导出符号 而不是dll中函数的圆型
以上四种调用惯例 和 两种编译方式所产生出的符号均不相同


仅有调用惯例为_cdecl 符号修饰方式为c的声明才能产生和函数原型相对应的符号(*.def 文件的作用)


按照以上四种方式编译出来的dll
如果均以
::GetProcAddress(::LoadLibrary("*.dll"), "GZipCompression") 
方式进行函数获取  仅有extern "C" + _cdecl 的方式编译的dll才能获取的到地址
其他方式编译出的dll 因为符号不匹配 GetProcAddress的返回值均为空


在c#中有所不同
如果按照extern "C" _cdecl的方式编译
[DllImport("Compressor.dll", EntryPoint = "GZipCompression", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)] 
[DllImport("Compressor.dll", EntryPoint = "GZipCompression", ExactSpelling = false, CallingConvention = CallingConvention.Stdcall)] 
都能进行正确的调用

而按照extern "C" _stdcall的方式编译
[DllImport("Compressor.dll", EntryPoint = "GZipCompression", ExactSpelling = false, CallingConvention = CallingConvention.Stdcall)]
能正常执行

[DllImport("Compressor.dll", EntryPoint = "GZipCompression", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)] 
的方式将会产生运行时的异常
System.EntryPointNotFoundException

而以c++方式编译(没有 extern "C" 声明)得到的符号 无论_cdecl , _stdcall 均无法进行调用
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值