Hi,
In an attempt to hook up to GTK+, I am trying to pass a Pascal array of varible size to C. Static arrays are fine, but these arrays carry some additional information like capacity and size, and I gues they could be received as a struct on the C-side. However, I cannot figure out the structure that the struc should have.
I do like this in Pascal:
procedure YGTK_init(var argc : CInteger; argv : array of CString); external name 'YGTK_init'; procedure Y_init; var argc : CInteger; argv : array[0..ParamCount] of CString; Counter : integer; begin argc := ParamCount+1; for Counter := 0 to ParamCount do begin argv[Counter] := NewCString(ParamStr(Counter)); end; YGTK_init(argc, argv); end;
And like this in C:
struct t_argv { int end; void *argv; };
void YGTK_init( int *argc, struct t_argv argv ) { printf("In ygtk.c:YGTK_init.\n"); printf("argv.end: %d\n", argv2.argc); printf("argv.argv address: %p\n", argv2.argv); printf("argv.argv int: %d\n", argv2.argv); printf("argv.argv string: %s\n", argv2.argv); printf("number of arguments: %d\n", *argc); }
So I figured out that the first element in the struct is an integer containing the length-1 of the array, but what it should look like for the rest I do not know yet. Do you have an idea?
Thanks, Bastiaan.
Bastiaan Veelo wrote:
So I figured out that the first element in the struct is an integer containing the length-1 of the array, but what it should look like for the rest I do not know yet. Do you have an idea?
Your approach relies on compiler-internal specifica that might change with future implementations of GPC. In C, I'd rather treat the GPC array as a pointer and access its contents and schema information with functions. Like this (untested):
Pascal unit:
type CStringArray = array of CString;
Function CStringArrayAt ( aArray: CStringArray; i: CInteger ): CString; attribute ( name = 'C_string_array_at' );
[...]
Function CStringArrayAt ( aArray: CStringArray; i: CInteger ): CString;
begin (* CStringArrayAt *) CStringArrayAt:= aArray [ i ]; end (* CStringArrayAt *);
C header:
char* C_string_array_at ( void* a_array, int i );
By this, you don't need to define a struct where you'd have to guess the correct position of the fields.
Regards,
Markus
On Sun, Jul 30, 2006 at 05:44:51PM +0200, Bastiaan Veelo wrote:
Hi,
In an attempt to hook up to GTK+, I am trying to pass a Pascal array of varible size to C. Static arrays are fine, but these arrays carry some additional information like capacity and size, and I gues they could be received as a struct on the C-side. However, I cannot figure out the structure that the struc should have.
I do like this in Pascal:
procedure YGTK_init(var argc : CInteger; argv : array of CString); external name 'YGTK_init';
If all you need is to pass argc and argv to the library, there are predefined variables CParamCount and CParameters (of type integer and PCString, respectively, which matches C int and **char).
Emil Jerabek
Emil Jerabek wrote:
If all you need is to pass argc and argv to the library, there are
predefined variables CParamCount and CParameters (of type integer and PCString, respectively, which matches C int and **char).
Emil Jerabek
Yes it is! But I get undeclared identifier errors when using these. Do I need to pull some switches for it to work?
Thanks, Bastiaan.
Bastiaan Veelo wrote:
Emil Jerabek wrote:
If all you need is to pass argc and argv to the library, there are
predefined variables CParamCount and CParameters (of type integer and PCString, respectively, which matches C int and **char).
Yes it is! But I get undeclared identifier errors when using these. Do I need to pull some switches for it to work?
In C you have to use the linker name, as revealed in gpc.pas:
CParamCount: Integer; attribute (name = '_p_CParamCount'); external; CParameters: PCStrings; attribute (name = '_p_CParameters'); external;
i.e.:
int _p_CParamCount; const char **_p_CParameters;
Frank
On Sun, Jul 30, 2006 at 07:55:33PM +0200, Bastiaan Veelo wrote:
Emil Jerabek wrote:
If all you need is to pass argc and argv to the library, there are
predefined variables CParamCount and CParameters (of type integer and PCString, respectively, which matches C int and **char).
Emil Jerabek
Yes it is! But I get undeclared identifier errors when using these. Do I need to pull some switches for it to work?
Ah, sorry. I shouldn't have said it is predefined, it is in the gpc unit. So "import gpc;" will do the trick.
Emil
Emil Jerabek wrote:
Ah, sorry. I shouldn't have said it is predefined, it is in the gpc unit. So "import gpc;" will do the trick.
I wrote:
In C you have to use the linker name, as revealed in gpc.pas:
CParamCount: Integer; attribute (name = '_p_CParamCount'); external; CParameters: PCStrings; attribute (name = '_p_CParameters'); external;
i.e.:
int _p_CParamCount; const char **_p_CParameters;
To avoid confusion, my suggestion was when you want to access the variables directly from C, Emil's when you want to pass them from Pascal. In fact, the latter is probably better, as it avoids relying on the linker name.
Frank
Bastiaan Veelo wrote:
So I figured out that the first element in the struct is an integer containing the length-1 of the array, but what it should look like for the rest I do not know yet. Do you have an idea?
Just to explain this mystery, for (BP style) open array parameters, GPC internally passes a hidden parameter containing the high limit of the array. (BTW, BP open arrays are always shifted to a low limit of zero, but this array is 0-based anyway already.) So this value contains the number of parameters (whereas argc in C contains the number including the 0th parameter, so is one higher). That your struct works is conincidence. It probably doesn't work on all platforms and may break with other GPC versions. So if anything, use a separate parameter in C. However, the type would have to be a Pascal Integer (not a CInteger) which isn't readily available in C.
However, I'd second what Markus wrote, to avoid relying on this passing mechanism at all, and pass only things to C that have a direct counter-part in C. Unfortunately, all higher-level dynamic array mechanisms (open array, conformant arrays, schemata) don't, so this often means a formally-unbounded plain array ...
Frank
Bastiaan Veelo wrote:
Hi,
In an attempt to hook up to GTK+, I am trying to pass a Pascal array of varible size to C...
You don't have to deal with C at all to use GTK. It has been ported to GPC. Check out: http://www.mirrorservice.org/sites/www.gnu-pascal.de/contrib/nicola/
If you decide to use it, let me know. I've already cleaned up one minor bug in it.