关于在Delphi中链接VC的obj文件(XE2以上版本)
2011-11-08 12:54
441 查看
个人用的少的东西,笔记之,以作记录
实际上老久之前,应该在Delphi中就可以链接使用Obj文件了吧,我用的第一个Delphi版本是D7,我记得他就可以了。至于再往前追述,就不晓得初始来源是哪个版本了。不过对于以前的版本的链接obj只能是OMF这个格式,这个格式是很早很早之前定义的一个文件格式,之后微软都转向了COFF这种格式了,也就是说VC编译出来的OBJ文件都是COFF格式。所以,以前要在Delphi中使用obj就要多走几步路程,要么使用VC编译的obj是COFF格式的,此时要使用COFF2OMF来进行转换,将COFF转换成OMF格式的,要么就是拿到C的源码,使用BCB等工具来编译以生成OMF的格式的obj。然后才能在Delphi中使用{$Link指令进行链接而使用里面的函数。
今天早上,俺在群中偶然听到了Delphi XE2可以支持COFF的obj静态链接了。这也就是说,可以直接使用VC编译生成的Obj文件了。之后写了一个测试的Demo,很简单的函数
#include "stdafx.h"
extern "C" {
extern int add(int x,int y);
}
int add(int x,int y)
{
return x+y;
}
编译生成了obj文件之后给Delphi使用,刚开始没改编译模式,生成的是Debug版本的obj文件,在Delphi中使用的时候,总是会报错误,无法发现add的前置引用,折腾了半天,也没搞好,之后编译成Release版本,在给Delphi使用,则运行成功!不知道是我搞的有问题还是说只能是Release版本可用,总之,发布Release的Obj给Delphi使用是没问题的。
不过这个例子就比较过于简单了,没实际作用,如果真实在开发过程中,那复杂度肯定是天差地别,于是找了一个VC版的Hook库,相对来说,这个库的代码就比较多一些了,而且也引用了好些系统API,比较复合实际开发的目的。我找的这个Hook库是海风月影大大的库,可以从这里下载,编译生成Obj文件之后,拿到Delphi中使用,编译就报了未声名
__imp__LoadLibraryA@4这样的错误,可见,这系统API在Obj中使用的,还不是真的将API函数的地址放入了,只是一个动态的预指定,于是编译的时候就找不到对应的函数了,所以我们需要在链接Obj的时候将这些导入函数在我们的程序中声名,比较蛋疼的是Delphi中的@是关键字,所以这个在VC的函数中,我们就需要将函数全部声名为C版本的函数导出和导入,C版本的会在函数名称前加入一个下划线,同时将WinApi的那套系统函数都在VC中写一个外置函数声名,API函数名字全部换掉,比如原来里面调用的是LoadLibrary这个是在Windows.h中声名的,我们现在不用这个,换一个声名
extern HMODULE __cdecl LoadLibraryExEx(LPCSTR lpLibFileName);
声名一个外部导入函数LoadLibraryExEx,然后将LoadLibrary都改成LoadLibraryExEx,同样道理,将API函数都做对应的处理之后编译
然后在Delphi中再将这些函数作为这个obj的导入函数,
function _LoadLibraryExEx(lpLibFileName: PAnsiChar): HMODULE;cdecl;
begin
Result := LoadLibraryA(lpLibFileName);
end;
这样包装一下,在进入链接Obj的时候,就会找到对应的函数了,搞定之后,还会发现,会报free的这个函数的错误,这个是VC的一个函数,函数在MSVCR70.DLL这个库中,所以也需要包装一下
extern void __cdecl free(void *);
malloc这个函数一样,之后在Delphi中,需要引用到MSVCR70.DLL这个动态库
procedure free(p: Pointer);cdecl;external 'MSVCR70.DLL';
procedure _free(p: Pointer);cdecl;
begin
free(p);
end;
这样就OK了,编译程序,在用通过
至于为何我要将VC中动态库的WINAPI都换成__cdecl的声名模式,可以自己去试一试,看看效果了!主要还是我前面说的Delphi中的@是一个关键字!
当然,这个Free和malloc也可以不用他这个Dll中的函数,可以直接用Delphi的也可以
比如
function _malloc(size_t: DWORD): Pointer;cdecl;
begin
GetMem(Result,Size_t);
end;
procedure _free(p: Pointer);cdecl;
begin
FreeMem(p);
end;
这样就免去了外部DLL的东西了!
源码下载
实际上老久之前,应该在Delphi中就可以链接使用Obj文件了吧,我用的第一个Delphi版本是D7,我记得他就可以了。至于再往前追述,就不晓得初始来源是哪个版本了。不过对于以前的版本的链接obj只能是OMF这个格式,这个格式是很早很早之前定义的一个文件格式,之后微软都转向了COFF这种格式了,也就是说VC编译出来的OBJ文件都是COFF格式。所以,以前要在Delphi中使用obj就要多走几步路程,要么使用VC编译的obj是COFF格式的,此时要使用COFF2OMF来进行转换,将COFF转换成OMF格式的,要么就是拿到C的源码,使用BCB等工具来编译以生成OMF的格式的obj。然后才能在Delphi中使用{$Link指令进行链接而使用里面的函数。
今天早上,俺在群中偶然听到了Delphi XE2可以支持COFF的obj静态链接了。这也就是说,可以直接使用VC编译生成的Obj文件了。之后写了一个测试的Demo,很简单的函数
#include "stdafx.h"
extern "C" {
extern int add(int x,int y);
}
int add(int x,int y)
{
return x+y;
}
编译生成了obj文件之后给Delphi使用,刚开始没改编译模式,生成的是Debug版本的obj文件,在Delphi中使用的时候,总是会报错误,无法发现add的前置引用,折腾了半天,也没搞好,之后编译成Release版本,在给Delphi使用,则运行成功!不知道是我搞的有问题还是说只能是Release版本可用,总之,发布Release的Obj给Delphi使用是没问题的。
不过这个例子就比较过于简单了,没实际作用,如果真实在开发过程中,那复杂度肯定是天差地别,于是找了一个VC版的Hook库,相对来说,这个库的代码就比较多一些了,而且也引用了好些系统API,比较复合实际开发的目的。我找的这个Hook库是海风月影大大的库,可以从这里下载,编译生成Obj文件之后,拿到Delphi中使用,编译就报了未声名
__imp__LoadLibraryA@4这样的错误,可见,这系统API在Obj中使用的,还不是真的将API函数的地址放入了,只是一个动态的预指定,于是编译的时候就找不到对应的函数了,所以我们需要在链接Obj的时候将这些导入函数在我们的程序中声名,比较蛋疼的是Delphi中的@是关键字,所以这个在VC的函数中,我们就需要将函数全部声名为C版本的函数导出和导入,C版本的会在函数名称前加入一个下划线,同时将WinApi的那套系统函数都在VC中写一个外置函数声名,API函数名字全部换掉,比如原来里面调用的是LoadLibrary这个是在Windows.h中声名的,我们现在不用这个,换一个声名
extern HMODULE __cdecl LoadLibraryExEx(LPCSTR lpLibFileName);
声名一个外部导入函数LoadLibraryExEx,然后将LoadLibrary都改成LoadLibraryExEx,同样道理,将API函数都做对应的处理之后编译
然后在Delphi中再将这些函数作为这个obj的导入函数,
function _LoadLibraryExEx(lpLibFileName: PAnsiChar): HMODULE;cdecl;
begin
Result := LoadLibraryA(lpLibFileName);
end;
这样包装一下,在进入链接Obj的时候,就会找到对应的函数了,搞定之后,还会发现,会报free的这个函数的错误,这个是VC的一个函数,函数在MSVCR70.DLL这个库中,所以也需要包装一下
extern void __cdecl free(void *);
malloc这个函数一样,之后在Delphi中,需要引用到MSVCR70.DLL这个动态库
procedure free(p: Pointer);cdecl;external 'MSVCR70.DLL';
procedure _free(p: Pointer);cdecl;
begin
free(p);
end;
这样就OK了,编译程序,在用通过
至于为何我要将VC中动态库的WINAPI都换成__cdecl的声名模式,可以自己去试一试,看看效果了!主要还是我前面说的Delphi中的@是一个关键字!
当然,这个Free和malloc也可以不用他这个Dll中的函数,可以直接用Delphi的也可以
比如
function _malloc(size_t: DWORD): Pointer;cdecl;
begin
GetMem(Result,Size_t);
end;
procedure _free(p: Pointer);cdecl;
begin
FreeMem(p);
end;
这样就免去了外部DLL的东西了!
源码下载
相关文章推荐
- 关于在Delphi中链接VC的obj文件(XE2以上版本)
- 关于在Delphi中链接VC的obj文件(XE2以上版本)
- 关于FileUpload控件选择文件时触发显示图像事件在IE7以上版本中不显示的问题
- 关于报表制作需要生成Office2007以上版本文件的注意点
- 关于Android7.0版本及其以上系统获取本地数据(图片和文件)报系统出现异常,正在退出问题
- 关于vc 链接时提示转换coff文件失败的【备忘-转载-来自百度知道】
- 关于x264 2011在VC2005及以上版本的编译
- 关于3.5以上版本FBX模型文件导入unity后不播放动作的问题
- Android2.2以上版本下载网络文件getContentLength()大小异常
- VC6使用VS2005(VS2008)的lib库文件,去除RTC链接错误
- delphi获取Exe文件版本信息的函数[转]
- 能在CAD2004以下版本里面打开2007以上版本文件的外挂
- VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结
- 关于android4.4及以上版本无法恢复还原短信的问题记录与解决
- 关于vc++ 6.0 编译器,点打开文件时自动关闭
- 关于百度地图SDK v3.6.0以上版本找不到PoiOverlay类(开源代码)的解决方法.
- VC中关于文件的操作
- 关于不打开文件批量转换的版本问题
- 关于ECSHOP在PHP5.4以上版本中的运行问题.txt
- 安卓学习笔记(16)-关于File(path).listFiles()在android7.0及以上版本运行返回null的问题【实测有效】