Thread: Passing parameters to a C function
<div class="Section1"><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> Hello,</span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> I have a question about passing parameters to a C function. Imagine the example by PostgreSQL:</span></font><pclass="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font><p class="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew"">PG_FUNCTION_INFO_V1(complex_add);</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> </span></font><pclass="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew"">Datum</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New"">complex_add(PG_FUNCTION_ARGS)</span></font><pclass="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><spanstyle="font-size:10.0pt;font-family:"Courier New"">{</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> Complex *a = (Complex *) PG_GETARG_POINTER(0);</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> Complex *b = (Complex *) PG_GETARG_POINTER(1);</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> Complex *result;</span></font><p class="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><spanstyle="font-size:10.0pt;font-family:"Courier New""> </span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> result = (Complex *) palloc(sizeof(Complex));</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> result->x = a->x + b->x;</span></font><p class="MsoNormal" style="margin-left:.5in"><font face="CourierNew" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> result->y = a->y + b->y;</span></font><pclass="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew""> PG_RETURN_POINTER(result);</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New"">}</span></font><pclass="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> So, in the same .C file I have to write another function that calls this one, for example: </span></font><pclass="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font><p class="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew"">void</span></font><p class="MsoNormal" style="margin-left:.5in"><font face="CourierNew" size="2"><span style="font-size:10.0pt;font-family:"Courier New"">test_main()</span></font><p class="MsoNormal"style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew"">{</span></font><p class="MsoNormal" style="margin-left:.5in"><font face="CourierNew" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> Complex *a;</span></font><p class="MsoNormal"style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew""> Complex *b;</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> </span></font><pclass="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew""> a = complex_in("(4.01, 3.77 )");</span></font><p class="MsoNormal"style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew""> printf("a = %s\n", complex_out(a));</span></font><p class="MsoNormal"style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew""> </span></font><p class="MsoNormal" style="margin-left:.5in"><font face="CourierNew" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> b = complex_in("(1.0,2.0)");</span></font><pclass="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><spanstyle="font-size:10.0pt;font-family:"Courier New""> printf("b = %s\n", complex_out(b));</span></font><pclass="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><span style="font-size:10.0pt;font-family:"CourierNew""> </span></font><p class="MsoNormal" style="margin-left:.5in"><font face="CourierNew" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> printf("a + b = %s\n", complex_out(complex_add(a,b)));</span></font><pclass="MsoNormal" style="margin-left:.5in"><font face="Courier New" size="2"><spanstyle="font-size:10.0pt;font-family:"Courier New"">}</span></font><p class="MsoNormal" style="margin-left:.5in"><fontface="Courier New" size="2"><span style="font-size:10.0pt;font-family:"Courier New""> </span></font><pclass="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial">But using version 1 calling convention it won’t work! So, how can I pass the ‘a’ and ‘b’ variables incomplex_add(?, ?)?</span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial">Thanks in advance!</span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font><p class="MsoNormal"><font face="Arial" size="2"><span style="font-size:10.0pt; font-family:Arial"> </span></font></div>
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