Talk:Use another language to call a function

I am unsure if this is same as C FFI, or not. If yes, then merge. --Dmitry-kazakov 13:57, 11 August 2009 (UTC)

It's not. Call foreign language function and C FFI are the same task in essence though (and there are other closely related ones too; this is an area needing some rationalization). —Donal Fellows 11:46, 17 August 2009 (UTC)

Task needs work/splitting?

While writing the Tcl implementation, it occurred to me that a number of languages might want to deal with the cases where a parameter is an ‘in’ parameter differently from the case given (really a single ‘out’ parameter, plus a bit of metadata to describe the buffer size). No time to work on this now though. —Donal Fellows 13:10, 18 August 2009 (UTC)

C code is wrong

#include <stdio.h>

extern int Query (char * Data, size_t * Length);

int main (int argc, char * argv [])
{
   char     Buffer [1024];
   unsigned Size = sizeof (Buffer);
   
   if (0 == Query (Buffer, &Size))
   {
      printf ("failed to call Query\n");
   }
   else
   {
      char * Ptr = Buffer;
      while (Size-- > 0) putchar (*Ptr++);
      putchar ('\n');
   }
}
#include <stdio.h>

int Query (char * Data, size_t * Length)
{
   printf("Length = %zu, 0x%zx\n", *Length, *Length);
   return 0;
}
$ cc -v
Reading specs from /usr/lib/gcc-lib/amd64-unknown-openbsd4.8/4.2.1/specs
Target: amd64-unknown-openbsd4.8
Configured with: OpenBSD/amd64 system compiler
Thread model: posix
gcc version 4.2.1 20070719 
$ cc -o main main.c query.c
main.c: In function 'main':
main.c:10: warning: passing argument 2 of 'Query' from incompatible pointer type
$ ./main 
Length = 7971459302400, 0x74000000400
failed to call Query

It should say 'Length = 1024', not 'Length = 7971459302400'. The problem is that main() passed an unsigned * but Query() expects size_t *. On my machine, unsigned is 4 bytes but size_t is 8 bytes.

I would like to fix the C code (by changing unsigned Size to size_t Size, and while there, by adding to main() some return statements), but I worry that if I fix the C code, then I will destroy all the examples that use the old C code. --Kernigh 15:45, 12 February 2011 (UTC)

I'd say fix it. Go saw that as a problem too. —Sonia 23:35, 12 February 2011 (UTC)
+1 on fix. There is a template to warn others to review their entries too, but I can't remember what it is ... ... nope, still can't remember. --Paddy3118 06:02, 13 February 2011 (UTC)
clarified-review? I made the change and added that template. I hope I did it right! —Sonia 07:48, 13 February 2011 (UTC)

Task focus and name?

This might be better named as "Demonstrate how a provided function can be called from a foreign language". --Markhobley 14:57, 5 June 2011 (UTC)

Task names should generally be short and sweet. A task summary might be appropriate. (Especially if we could implement something like task summaries as semantic properties) --Michael Mol 15:20, 6 June 2011 (UTC)
What about "Demonstrate a function call from a foreign language"? --Markhobley 17:44, 6 June 2011 (UTC)
Near as I can figure, the task title is about as good as it can be. It's an inverse of Call foreign language function, so if anything, it ought to be renamed Call function from foreign language, removing the article 'a'. It seems good enough to not warrant that kind of redirect, though. --Michael Mol 04:57, 7 June 2011 (UTC)
The current title can be read one of two ways:
  • Call (a function from a foreign language)
  • (Call a function) from a foreign language

- Hence I suggested renaming this task. --14:10, 7 June 2011 (UTC)

Hm. I see your point. I don't like the full-sentence approach for task names, though. Other ideas? --Michael Mol 16:24, 7 June 2011 (UTC)
Maybe we could reverse the phrasing somehow: "Use a foreign language to call a function". --18:58, 7 June 2011 (UTC)

I don't know why we chose that particular function for the task description. Couldn't we have just done something that produces a result from a couple of numbers? The example in the task description requires an unnecessary amount of work to demonstrate something that could in essence be much simpler. --Markhobley 14:57, 5 June 2011 (UTC)

I think the reason in this case was to intentionally call out a non-trivial area of language compatibility. Being able to pass strings back and forth between languages (especially where some of the languages have very different ways of exposing strings to programmers) is a touchy subject. That said, it may be appropriate to split the task between trivial and non-trivial scenarios. --Michael Mol 15:20, 6 June 2011 (UTC)

Is the pipe option of pico lisp fair play? It's a ubiquitous, and easy solution.--Dave 04:43, 14 March 2012 (UTC)

Trying to build the Ada solution fails, perhaps I am doing something stupid.

I get a run-time error: raised INTERFACES.C.STRINGS.UPDATE_ERROR : i-cstrin.adb:260

cat ./test_it.bash

  1. !/bin/bash

gcc -v -c ./main.c gnatmake -v -c ./exported.adb gnatbind -v -n ./exported.ali gnatlink -v ./exported.ali ./main.o -o ./main ./main 2>&1 | tee ./NOTE.txt gnatclean ./exported rm ./main ./main.o


cat ./exported.ads

with Interfaces.C;          use Interfaces.C;
with Interfaces.C.Strings;  use Interfaces.C.Strings;

package Exported is
   function Query (Data : chars_ptr; Size : access size_t)
      return int;
   pragma Export (C, Query, "Query");
end Exported;


cat ./exported.adb

package body Exported is
   function Query (Data : chars_ptr; Size : access size_t)
      return int is
      Result : char_array := "Here am I";
   begin
      if Size.all < Result'Length then
         return 0;
      else
         Update (Data, 0, Result);
         Size.all := Result'Length;
         return 1;
      end if;
   end Query;
end Exported;


cat ./main.c

#include <stdio.h>

extern int Query (char * Data, size_t * Length);

int main (int argc, char * argv [])
{
   char     Buffer [1024];
   size_t   Size = sizeof (Buffer);

   if (0 == Query (Buffer, &Size))
   {
      printf ("failed to call Query\n");
   }
   else
   {
      char * Ptr = Buffer;
      while (Size-- > 0) putchar (*Ptr++);
      putchar ('\n');
   }
}


I have a lot of output (as I used the verbose flag on all of the build commands)...but none of it seems to point to a make and/or link error...I can provide the output if desired.

Environment: MacOS 14.6.1 M1 chip (arm64) gnatmake -v

GNATMAKE 14.1.0 Copyright (C) 1992-2024, Free Software Foundation, Inc.


Thanks, Retired Build Engineer

I'm not that knowledgeable of Ada, but Googling ada update_error found this:
https://comp.lang.ada.narkive.com/EzyUTCFS/interfaces-c-string-update
which suggests you need to null terminate the string (which C would expect in general but probably not in this example) and probably set Check to false in the Update call.
--Tigerofdarkness (talk) 07:48, 14 September 2024 (UTC)
Return to "Use another language to call a function" page.