Обсуждение: Passing parameters to a C function
Hello,
I have a question about passing parameters to a C function. Imagine the example by PostgreSQL:
PG_FUNCTION_INFO_V1(complex_add);
Datum
complex_add(PG_FUNCTION_ARGS)
{
Complex *a = (Complex *) PG_GETARG_POINTER(0);
Complex *b = (Complex *) PG_GETARG_POINTER(1);
Complex *result;
result = (Complex *) palloc(sizeof(Complex));
result->x = a->x + b->x;
result->y = a->y + b->y;
PG_RETURN_POINTER(result);
}
So, in the same .C file I have to write another function that calls this one, for example:
void
test_main()
{
Complex *a;
Complex *b;
a = complex_in("(4.01, 3.77 )");
printf("a = %s\n", complex_out(a));
b = complex_in("(1.0,2.0)");
printf("b = %s\n", complex_out(b));
printf("a + b = %s\n", complex_out(complex_add(a,b)));
}
But using version 1 calling convention it won’t work! So, how can I pass the ‘a’ and ‘b’ variables in complex_add(?, ?)?
Thanks in advance!
On Wed, May 30, 2007 at 11:26:01AM -0300, Rodrigo Sakai wrote: > I have a question about passing parameters to a C function. Imagine the > example by PostgreSQL: > > PG_FUNCTION_INFO_V1(complex_add); > But using version 1 calling convention it won't work! So, how can I pass the > 'a' and 'b' variables in complex_add(?, ?)? Use the DirectFunctionCalln functions in fmgr. Have a nice day, -- Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/ > From each according to his ability. To each according to his ability to litigate.
Martijn van Oosterhout <kleptog@svana.org> writes:
> On Wed, May 30, 2007 at 11:26:01AM -0300, Rodrigo Sakai wrote:
>> But using version 1 calling convention it won't work! So, how can I pass the
>> 'a' and 'b' variables in complex_add(?, ?)?
> Use the DirectFunctionCalln functions in fmgr.
There are boatloads of examples in the existing datatype code, for
instance this function in geo_ops.c, which is just applying
close_sb() followed by dist_pb():
Datum
dist_sb(PG_FUNCTION_ARGS)
{ LSEG *lseg = PG_GETARG_LSEG_P(0); BOX *box = PG_GETARG_BOX_P(1); Point *tmp; Datum
result;
tmp = DatumGetPointP(DirectFunctionCall2(close_sb, LsegPGetDatum(lseg),
BoxPGetDatum(box))); result = DirectFunctionCall2(dist_pb,
PointPGetDatum(tmp), BoxPGetDatum(box));
PG_RETURN_DATUM(result);
}
All that casting to and from Datum is a bit of a pain, but it's worth it
to have a uniform, portable function API.
I strongly suggest adding some appropriate cast macros for your own
datatype, like the ones being used here, instead of dealing directly
with low-level operations like PG_GETARG_POINTER.
regards, tom lane