Delphi Const Array
Please help! I need this conversion to write wrapper for some C headers for Delphi.
As an example:
How can I convert 'array of const' to 'varargs'?
The last airbender 2 confirmed. Potential release date. In reality, there are many who have said that they do not believe that the Last Airbender 2 should be released. The original struggled and many believe that the damage has been done. Despite this, M. Night Shyamalan has stated that he does have plans to make the film but he wants to release one of his other ideas first. Initially, Paramount representatives set the release date of «The Last Airbender 2» for May 2012; however it wasn’t released due to some budgetary concerns. According to several Internet resources, Warner Bros. Company is to finance the second part provided Night Shyamalan, who has exhausted his potential, won’t be responsible for production.
edit: function PushString is actually inside the record (I gave a simplified example), and I do not have direct access to pushfstring. Direct call is excluded.
edit 2:I write the units for LUA library for Delphi and the case is quite important for me.
Specifying and providing all the details of the matter - I have this function in C:
In Delphi I have something like this:
LuaLibrary.pas
dtxLua.pas
and in other units like Lua.pas i use only TLuaState from dtxLua.pas (because LuaLibrary is bulky, dtxLua is my wrapper), for many useful and cool things..
4 Answers
I'm guessing that the prototype for pushfstring
is somewhat like this:
If it isn't, and is instead:
.. then I should have you covered also.
In C, if you have to pass on a call from one variadic function to another, you should use va_list
, va_start
and va_end
, and call the v
version of the function. So, if you were implementing printf
yourself, you might use vsprintf
to format the string - you can't call sprintf
directly and pass along the variadic argument list. You need to use va_list
and friends.
It's pretty awkward to handle C's va_list
from Delphi, and technically it shouldn't be done - the implementation of va_list
is specific to the C compiler vendor's runtime.
However, we can try. Suppose we have a little class - though I made it a record for ease of use:
Using this record, we can manually construct the call frame expected for various C calls. C's calling convention on x86 is to pass arguments from right to left on the stack, with the caller cleaning up. Here's the skeleton of a generic C calling routine:
Taking printf
as an example:
Calling the va_list
version is slightly more involved, as the va_list
argument's location needs to be placed carefully where it is expected:
Notes:
The above expects x86 on Windows. Microsoft C, bcc32 (Embarcadero C++) and gcc all pass
va_list
in the same way (a pointer to the first variadic argument on the stack), according to my experiments, so it should work for you; but as soon as the x86 on Windows assumption is broken, expect this to possibly break too.The stack is swapped to ease with its construction. This can be avoided with more work, but passing
va_list
also becomes trickier, as it needs to point at the arguments as if they were passed on the stack. As a consequence, the code needs to make an assumption about how much stack the called routine uses; this example assumes 8K, but this may be too small. Increase if necessary.
The wrapper you are trying to write is possible in Free Pascal, since Free Pascal supports 2 equvalent declarations for varargs external functions:
so instead of
you should write
Update: I have tried the same trick in Delphi, but it does not work:
An 'array of const' is actually an array of TVarRec, which is a special variant type. It's not compatible with varargs, and you really should be able to call the varargs function directly without a wrapper around it.
Barry Kelly inspired me to seeking a solution without replacing the stack.. Here is the solution (probably could also use the Invoke from the rtti unit, instead RealCall_CDecl).
Not the answer you're looking for? Browse other questions tagged delphiarraysvariadic-functions or ask your own question.
Is there a way in Delphi declaring an array of strings such as following one?
4 Answers
In XE7 you can declare a dynamic array constant like this:
You can use dynamic arrays and try this:
While this does do a run-time initialization of a dynamic array on the heap, it also shows that Delphi supports a 'pseudo-constructor' on dynamic arrays that allow in-place initialization. (NOTE: the above code isn't thread-safe).
Now all you need to do to find out the length of the array, is use the Length() standard function, or to find the allowed index range, use the Low() and High() standard functions.
If you're using an older version of Delphi, replace the TArray with your own dynamic-array string type such as:
You can do this in a indirect way. Create a function like:
and call this function like:
where: