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.
精彩评论