开发者

Can I use C headers in Delphi?

Is it possible to compile C headers with the Rad Studio XE C++ compiler and link them with Delphi code?

Thus eliminating the need to convert header files to pascal ?

The reason for the question is..

C - Header definition:

DLLEXPORT int url_engine_version(char *version, size_t length);

Attempt at Delphi Definition

function url_engine_version(version: PByte; var length: cardinal): integer;
  cdecl; external 'corplib.dll';

Main app tried to call it using:

engVer: Pointer;
engLen: cardinal;

engLen := 64;
GetMem(engVer,engLen);
url_engine_version(engVer,engLen);

But Delphi AV's when it tries to call the routine.

Working C# definition - Chick works if I pa开发者_运维知识库ss a StringBuilder predefinded as length 64

[DllImport("corplib.dll", CharSet = CharSet.Ansi,
           CallingConvention = CallingConvention.Cdecl)]
public static extern int url_engine_version(StringBuilder version, [Out] int length);


The answer to your actual question is: No. Sorry.

However, I think in this case the problem is quite simple...

Either the C Header you have reproduced here is wrong or the C# declaration is or you have just been very lucky to not have the C# code crash and burn as badly as the Delphi code.

The problem I think is that the C Header declares the length parameter as a SIZE_T, NOT a pointer to a SIZE_T. i.e. it is an input parameter, not an output or in/out parameter.

You presumably use length to specify the size of buffer allocated for the pointer you pass in version. I further presume that the function returns the number of actual bytes used for the data placed in the version buffer.

The Delphi version crashes, I believe, because by specifying length as var, you are passing length by reference, i.e. the function receives not "64" but a pointer to the value "64", but it is using this pointer value, not the 64 value.

The C# code may be dodging the bullet by (also incorrectly, if the C Header itself is correct) declaring the parameter as out. This may translate into something that, if not correct, is at least not as "damagingly incorrect" at runtime.

I think simply removing the "var" from the length parameter declaration should solve your problem:

function url_engine_version(aVersion: PByte; aLength: cardinal): integer; cdecl; external 'corplib.dll';


The main problem with converting are differences in the type system. A good delphi header can't be derived from c.

For example c doesn't distinguish pointers to one element and pointers to arrays. It doesn't distinguish bools and ints. A char* can mean a zero terminated string, a pointer to bytes, a pointer to a single char, a char passed by reference,...

And in your example the delphi code passes the last parameter by reference(i.e. as pointer to UInt32) and the c code doesn't. But I don't understand why the C# code works.


Project JEDI have done a lot of C header conversions for Delphi. They have an excellent set of resources, tutorials etc. on their website.

They also have a tool that can automate this which was actually derived from original code by Bob Swart.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜