关于在Delphi中链接VC的obj文件(XE2以上版本)

     个人用的少的东西,笔记之,以作记录

     实际上老久之前,应该在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的东西了!

 

 

 

C语言如何调用delphi的rtl库函数 

问题如下:
主程序用delphi写,子函数因为指针处理方面的问题,需要用C写,先用bcc32.exe编译成obj,再用delphi联编成EXE。
加这个编译符就可以了:{$LINK 'FSK.obj'}

关键问题是,C语言中的内存管理不想用C的库函数realloc和calloc,而是想使用delphi的库函数AllocMem,ReAllocMem,FreeMem。因为,这些rtl函数在delphi的主程序中也会使用到,所以何必又要去联编C的Lib。

这个就麻烦了,第一是怎么在C中进行声明,第二是编译器如何操作进行联编。

说明一下版本,delphi是7.0,bcc是那个免费的bcc 5.5.1
不调用库函数的obj联编没有一点问题。

声明不用你操心,用哪个函数是链接器的事儿,跟编译器没关系
简单的说,就是在.pas中写个与c语言库符号表中malloc/free等函数表示方式相同的形式,比如:

Delphi(Pascal) code
  function _malloc(n: Integer): Pointer; cdecl;  begin    GetMem(Result, n);  end;   
  


在链接的时候,链接器就可以使用该符号链接了
例子可以看delphi提供的jpeg.pas单元,它就是链接到c语言编译的ijl库。新版本的delphi在source目录中直接就有源代码和.obj文件,老版本delphi在光盘目录中也能找到

没有想到如此刁钻的问题竟有如此巧妙的解法,太佩服了。
真的是融会贯通的编译器和连接器的道理才能想得出来。

转自:http://www.189works.com/article-41336-2.html

           http://www.newsmth.net

 

要在Qt使用OpenGL 3.3或更高版本来渲染一个OBJ文件,您需要完成以下步骤: 1. 在Qt创建一个OpenGL窗口: ```c++ class GLWidget : public QOpenGLWidget { public: GLWidget(QWidget *parent = 0); ~GLWidget(); protected: void initializeGL() override; void paintGL() override; void resizeGL(int w, int h) override; }; ``` 2. 在initializeGL函数初始化OpenGL环境,并编译和链接您的着色器程序: ```c++ void GLWidget::initializeGL() { initializeOpenGLFunctions(); // Create and compile your shader program QOpenGLShaderProgram* shaderProgram = new QOpenGLShaderProgram(this); shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, "vertexShader.glsl"); shaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, "fragmentShader.glsl"); shaderProgram->link(); shaderProgram->bind(); } ``` 3. 在paintGL函数使用您的着色器程序和OBJ文件的数据绘制场景: ```c++ void GLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set up your shader uniforms and attributes shaderProgram->setUniformValue("projection", projection); shaderProgram->setUniformValue("view", view); shaderProgram->setUniformValue("model", model); shaderProgram->setAttributeArray("position", vertices.constData(), 3, sizeof(Vertex)); shaderProgram->setAttributeArray("normal", normals.constData(), 3, sizeof(Vertex)); shaderProgram->setAttributeArray("texCoord", texCoords.constData(), 2, sizeof(Vertex)); shaderProgram->enableAttributeArray("position"); shaderProgram->enableAttributeArray("normal"); shaderProgram->enableAttributeArray("texCoord"); // Draw your OBJ file glDrawArrays(GL_TRIANGLES, 0, vertices.size()); shaderProgram->disableAttributeArray("position"); shaderProgram->disableAttributeArray("normal"); shaderProgram->disableAttributeArray("texCoord"); } ``` 4. 在resizeGL函数更新OpenGL视口: ```c++ void GLWidget::resizeGL(int w, int h) { glViewport(0, 0, w, h); } ``` 5. 确保您的OBJ文件包含顶点位置、法线和纹理坐标数据,并且您可以正确地解析和加载它们。 这只是一个基本的框架,您需要根据您的项目需求进行修改和扩展。您可以使用第三方库,如Assimp,来加载和解析OBJ文件的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值