Call a foreign-language function: Difference between revisions
Content added Content deleted
Puppydrum64 (talk | contribs) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 26: | Line 26: | ||
'''Z80 Code:''' |
'''Z80 Code:''' |
||
< |
<syntaxhighlight lang=z80>org &0000 ;execution resets here after the 68000 resets the Z80 and sends a bus request. |
||
jr start |
jr start |
||
Line 55: | Line 55: | ||
ExampleFunction: ;ADDR: &0072($A00072) |
ExampleFunction: ;ADDR: &0072($A00072) |
||
ret ;for simplicity this does nothing but in reality you'd have it do something sound-related here.</ |
ret ;for simplicity this does nothing but in reality you'd have it do something sound-related here.</syntaxhighlight> |
||
Here's the 68000 code that will get the Z80 to call this function: |
Here's the 68000 code that will get the Z80 to call this function: |
||
< |
<syntaxhighlight lang=68000devpac>Z80_Call: |
||
MOVE.W #$100,$A11100 ;write: z80 reset |
MOVE.W #$100,$A11100 ;write: z80 reset |
||
.wait: |
.wait: |
||
Line 74: | Line 74: | ||
MOVE.B #$FF,$A01F01 ;unlock the semaphore |
MOVE.B #$FF,$A01F01 ;unlock the semaphore |
||
MOVE.W #0,$A11100 ;Z80 Bus Request - after this write, the Z80 will start executing code.</ |
MOVE.W #0,$A11100 ;Z80 Bus Request - after this write, the Z80 will start executing code.</syntaxhighlight> |
||
=={{header|8th}}== |
=={{header|8th}}== |
||
< |
<syntaxhighlight lang=forth> |
||
\ tell 8th what the function expects: |
\ tell 8th what the function expects: |
||
"ZZ" "strdup" func: strdup |
"ZZ" "strdup" func: strdup |
||
Line 86: | Line 86: | ||
\ the ".s" will show both strings and you can see they are different items on the stack |
\ the ".s" will show both strings and you can see they are different items on the stack |
||
free \ let the c library free the string |
free \ let the c library free the string |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
Ada provides standard interfaces to [[C]], [[C++]], [[Fortran]] and [[Cobol]]. Other language interfaces can be provided as well, but are not mandatory. Usually it is possible to communicate to any language that supports calling conventions standard to the [[OS]] ('''cdecl''', '''stdcall''' etc). |
Ada provides standard interfaces to [[C]], [[C++]], [[Fortran]] and [[Cobol]]. Other language interfaces can be provided as well, but are not mandatory. Usually it is possible to communicate to any language that supports calling conventions standard to the [[OS]] ('''cdecl''', '''stdcall''' etc). |
||
< |
<syntaxhighlight lang=Ada>with Ada.Text_IO; use Ada.Text_IO; |
||
with Interfaces.C; use Interfaces.C; |
with Interfaces.C; use Interfaces.C; |
||
with Interfaces.C.Strings; use Interfaces.C.Strings; |
with Interfaces.C.Strings; use Interfaces.C.Strings; |
||
Line 104: | Line 104: | ||
Put_Line (Value (S2)); |
Put_Line (Value (S2)); |
||
Free (S2); |
Free (S2); |
||
end Test_C_Interface;</ |
end Test_C_Interface;</syntaxhighlight> |
||
=={{header|Aikido}}== |
=={{header|Aikido}}== |
||
There are two ways to call a <em>native</em> function in Aikido. The first is to write a wrapper function in C++ that is invoked from the Aikido interpreter. In a C++ file: |
There are two ways to call a <em>native</em> function in Aikido. The first is to write a wrapper function in C++ that is invoked from the Aikido interpreter. In a C++ file: |
||
< |
<syntaxhighlight lang=aikido>#include <aikido.h> |
||
extern "C" { // need C linkage |
extern "C" { // need C linkage |
||
Line 120: | Line 120: | ||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Then in the Aikido program: |
Then in the Aikido program: |
||
< |
<syntaxhighlight lang=aikido>native function strdup(s) |
||
println (strdup ("Hello World!"))</ |
println (strdup ("Hello World!"))</syntaxhighlight> |
||
The second way is to use a <em>raw native</em> function. These functions must adhere to a defined set of rules and can be called directly from the Aikido interpreter. In the case of <code>strdup</code> we need to play a nasty trick because it returns a pointer that we need to print as a string. |
The second way is to use a <em>raw native</em> function. These functions must adhere to a defined set of rules and can be called directly from the Aikido interpreter. In the case of <code>strdup</code> we need to play a nasty trick because it returns a pointer that we need to print as a string. |
||
< |
<syntaxhighlight lang=aikido>native function strdup (s) // declare native |
||
native function free(p) // also need to free the result |
native function free(p) // also need to free the result |
||
Line 141: | Line 141: | ||
p++ |
p++ |
||
} |
} |
||
free (s) // done with the memory now</ |
free (s) // done with the memory now</syntaxhighlight> |
||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
Line 149: | Line 149: | ||
Note that I chose a non-trivial library function because the suggested strdup() doesn't really demonstrate the technique all that well. |
Note that I chose a non-trivial library function because the suggested strdup() doesn't really demonstrate the technique all that well. |
||
< |
<syntaxhighlight lang=algol68> |
||
BEGIN |
BEGIN |
||
MODE PASSWD = STRUCT (STRING name, passwd, INT uid, gid, STRING gecos, dir, shell); |
MODE PASSWD = STRUCT (STRING name, passwd, INT uid, gid, STRING gecos, dir, shell); |
||
Line 217: | Line 217: | ||
FI |
FI |
||
END |
END |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 225: | Line 225: | ||
=={{header|ARM Assembly}}== |
=={{header|ARM Assembly}}== |
||
{{works with|as|Raspberry Pi}} |
{{works with|as|Raspberry Pi}} |
||
< |
<syntaxhighlight lang=ARM Assembly> |
||
/* ARM assembly Raspberry PI */ |
/* ARM assembly Raspberry PI */ |
||
Line 279: | Line 279: | ||
pop {r0,r1,r2,r7,lr} @ restaur des 2 registres */ |
pop {r0,r1,r2,r7,lr} @ restaur des 2 registres */ |
||
bx lr @ return |
bx lr @ return |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Arturo}}== |
=={{header|Arturo}}== |
||
Line 285: | Line 285: | ||
'''C Library''' |
'''C Library''' |
||
< |
<syntaxhighlight lang=c>// compile with: |
||
// clang -c -w mylib.c |
// clang -c -w mylib.c |
||
// clang -shared -o libmylib.dylib mylib.o |
// clang -shared -o libmylib.dylib mylib.o |
||
Line 297: | Line 297: | ||
int doubleNum(int num){ |
int doubleNum(int num){ |
||
return num * 2; |
return num * 2; |
||
}</ |
}</syntaxhighlight> |
||
'''Calling from Arturo''' |
'''Calling from Arturo''' |
||
< |
<syntaxhighlight lang=rebol>; call an external function directly |
||
call.external: "mylib" 'sayHello ["John"] |
call.external: "mylib" 'sayHello ["John"] |
||
Line 314: | Line 314: | ||
loop 1..3 'x [ |
loop 1..3 'x [ |
||
print ["The double of" x "is" doubleNum x] |
print ["The double of" x "is" doubleNum x] |
||
]</ |
]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 324: | Line 324: | ||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
from the documentation for dllcall: < |
from the documentation for dllcall: <syntaxhighlight lang=AutoHotkey>; Example: Calls the Windows API function "MessageBox" and report which button the user presses. |
||
WhichButton := DllCall("MessageBox", "int", "0", "str", "Press Yes or No", "str", "Title of box", "int", 4) |
WhichButton := DllCall("MessageBox", "int", "0", "str", "Press Yes or No", "str", "Title of box", "int", 4) |
||
MsgBox You pressed button #%WhichButton%.</ |
MsgBox You pressed button #%WhichButton%.</syntaxhighlight> |
||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
{{works with|BBC BASIC for Windows}} |
{{works with|BBC BASIC for Windows}} |
||
< |
<syntaxhighlight lang=bbcbasic> SYS "LoadLibrary", "MSVCRT.DLL" TO msvcrt% |
||
SYS "GetProcAddress", msvcrt%, "_strdup" TO `strdup` |
SYS "GetProcAddress", msvcrt%, "_strdup" TO `strdup` |
||
SYS "GetProcAddress", msvcrt%, "free" TO `free` |
SYS "GetProcAddress", msvcrt%, "free" TO `free` |
||
Line 338: | Line 338: | ||
PRINT $$address% |
PRINT $$address% |
||
SYS `free`, address% |
SYS `free`, address% |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|C}}== |
=={{header|C}}== |
||
===Assembly via GCC=== |
===Assembly via GCC=== |
||
Assembly code can be embedded and compiled via GCC. |
Assembly code can be embedded and compiled via GCC. |
||
<syntaxhighlight lang=C> |
|||
<lang C> |
|||
#include <stdlib.h> |
#include <stdlib.h> |
||
#include <stdio.h> |
#include <stdio.h> |
||
Line 368: | Line 368: | ||
return 0 ; |
return 0 ; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 381: | Line 381: | ||
===Python=== |
===Python=== |
||
'''IMPORTANT''' : The following implementation has been tested against Python 2.7, this won't work on a system which does not have the relevant files installed. Also pay attention to the compilation flags. |
'''IMPORTANT''' : The following implementation has been tested against Python 2.7, this won't work on a system which does not have the relevant files installed. Also pay attention to the compilation flags. |
||
< |
<syntaxhighlight lang=C>#include <python2.7/Python.h> |
||
int main() |
int main() |
||
Line 396: | Line 396: | ||
Py_Finalize(); |
Py_Finalize(); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
'''Compilation''' : Change 2.7 and relevant paths for a different Python version / different install location |
'''Compilation''' : Change 2.7 and relevant paths for a different Python version / different install location |
||
<pre> |
<pre> |
||
Line 413: | Line 413: | ||
In addition, this code demonstrates a call to a FORTRAN function defined as |
In addition, this code demonstrates a call to a FORTRAN function defined as |
||
< |
<syntaxhighlight lang=cpp>FUNCTION MULTIPLY(X, Y) |
||
DOUBLE PRECISION MULTIPLY, X, Y</ |
DOUBLE PRECISION MULTIPLY, X, Y</syntaxhighlight> |
||
Note that the calling convention of FORTRAN depends on the system and the used FORTRAN compiler, and sometimes even on the command line options used for the compiler; here, GNU Fortran with no options is assumed. |
Note that the calling convention of FORTRAN depends on the system and the used FORTRAN compiler, and sometimes even on the command line options used for the compiler; here, GNU Fortran with no options is assumed. |
||
< |
<syntaxhighlight lang=cpp>#include <cstdlib> // for C memory management |
||
#include <string> // for C++ strings |
#include <string> // for C++ strings |
||
#include <iostream> // for output |
#include <iostream> // for output |
||
Line 457: | Line 457: | ||
// free, not delete, nor delete[], nor operator delete |
// free, not delete, nor delete[], nor operator delete |
||
std::free(msg2); |
std::free(msg2); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
{{libheader|clojure-jna}} |
{{libheader|clojure-jna}} |
||
Since Clojure is hosted on the JVM, you can follow the same approach as the [[#Java|Java]] solution and invoke your Java class from Clojure: |
Since Clojure is hosted on the JVM, you can follow the same approach as the [[#Java|Java]] solution and invoke your Java class from Clojure: |
||
< |
<syntaxhighlight lang=clojure>(JNIDemo/callStrdup "Hello World!")</syntaxhighlight> |
||
Alternatively, to avoid having to create a library in native code you could use JNA and the clojure-jna library for convenience. Here's how you can invoke ''strcmp'' from the libc shared library: |
Alternatively, to avoid having to create a library in native code you could use JNA and the clojure-jna library for convenience. Here's how you can invoke ''strcmp'' from the libc shared library: |
||
< |
<syntaxhighlight lang=clojure>(require '[net.n01se.clojure-jna :as jna]) |
||
(jna/invoke Integer c/strcmp "apple" "banana" ) ; returns -1 |
(jna/invoke Integer c/strcmp "apple" "banana" ) ; returns -1 |
||
Line 471: | Line 471: | ||
(jna/invoke Integer c/strcmp "banana" "apple" ) ; returns 1 |
(jna/invoke Integer c/strcmp "banana" "apple" ) ; returns 1 |
||
(jna/invoke Integer c/strcmp "banana" "banana" ) ; returns 0</ |
(jna/invoke Integer c/strcmp "banana" "banana" ) ; returns 0</syntaxhighlight> |
||
=={{header|CMake}}== |
=={{header|CMake}}== |
||
Line 479: | Line 479: | ||
'''CMakeLists.txt''' |
'''CMakeLists.txt''' |
||
< |
<syntaxhighlight lang=cmake>cmake_minimum_required(VERSION 2.6) |
||
project("outer project" C) |
project("outer project" C) |
||
Line 503: | Line 503: | ||
2012 / 500 = ${quot} |
2012 / 500 = ${quot} |
||
2012 % 500 = ${rem} |
2012 % 500 = ${rem} |
||
")</ |
")</syntaxhighlight> |
||
'''div/CMakeLists.txt''' |
'''div/CMakeLists.txt''' |
||
< |
<syntaxhighlight lang=cmake>cmake_minimum_required(VERSION 2.6) |
||
project(div C) |
project(div C) |
||
Line 513: | Line 513: | ||
# Compile cmDIV from div-command.c |
# Compile cmDIV from div-command.c |
||
add_library(cmDIV MODULE div-command.c)</ |
add_library(cmDIV MODULE div-command.c)</syntaxhighlight> |
||
'''div/div-command.c''' |
'''div/div-command.c''' |
||
< |
<syntaxhighlight lang=c>#include <cmCPluginAPI.h> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Line 570: | Line 570: | ||
info->InitialPass = initial_pass; |
info->InitialPass = initial_pass; |
||
api = info->CAPI; |
api = info->CAPI; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|COBOL}}== |
=={{header|COBOL}}== |
||
Tested with GnuCOBOL |
Tested with GnuCOBOL |
||
< |
<syntaxhighlight lang=cobol> identification division. |
||
program-id. foreign. |
program-id. foreign. |
||
Line 601: | Line 601: | ||
display "error calling free" upon syserr |
display "error calling free" upon syserr |
||
end-if |
end-if |
||
goback.</ |
goback.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 614: | Line 614: | ||
{{libheader|CFFI}} |
{{libheader|CFFI}} |
||
< |
<syntaxhighlight lang=lisp>CL-USER> (let* ((string "Hello World!") |
||
(c-string (cffi:foreign-funcall "strdup" :string string :pointer))) |
(c-string (cffi:foreign-funcall "strdup" :string string :pointer))) |
||
(unwind-protect (write-line (cffi:foreign-string-to-lisp c-string)) |
(unwind-protect (write-line (cffi:foreign-string-to-lisp c-string)) |
||
Line 620: | Line 620: | ||
(values)) |
(values)) |
||
Hello World! |
Hello World! |
||
; No value</ |
; No value</syntaxhighlight> |
||
=={{header|Crystal}}== |
=={{header|Crystal}}== |
||
Crystal allows to easily interface with C functions, both from object files and shared libraries. |
Crystal allows to easily interface with C functions, both from object files and shared libraries. |
||
< |
<syntaxhighlight lang=ruby>@[Link("c")] # name of library that is passed to linker. Not needed as libc is linked by stdlib. |
||
lib LibC |
lib LibC |
||
fun free(ptr : Void*) : Void |
fun free(ptr : Void*) : Void |
||
Line 635: | Line 635: | ||
LibC.free p # pointer can be freed as String.new(Char*) makes a copy of data |
LibC.free p # pointer can be freed as String.new(Char*) makes a copy of data |
||
puts s2</ |
puts s2</syntaxhighlight> |
||
=={{header|D}}== |
=={{header|D}}== |
||
< |
<syntaxhighlight lang=d>import std.stdio: writeln; |
||
import std.string: toStringz; |
import std.string: toStringz; |
||
import std.conv: to; |
import std.conv: to; |
||
Line 673: | Line 673: | ||
free(str1); |
free(str1); |
||
free(str2); |
free(str2); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>str1: Hello World! |
<pre>str1: Hello World! |
||
Line 687: | Line 687: | ||
The file first has to be bound to your unit: |
The file first has to be bound to your unit: |
||
< |
<syntaxhighlight lang=delphi> |
||
{$O myhello.obj} |
{$O myhello.obj} |
||
</syntaxhighlight> |
|||
</lang> |
|||
The next step is to do an external declaration for the function: |
The next step is to do an external declaration for the function: |
||
< |
<syntaxhighlight lang=delphi> |
||
procedure Hello(S: PChar); stdcall; external; |
procedure Hello(S: PChar); stdcall; external; |
||
</syntaxhighlight> |
|||
</lang> |
|||
Afterwards usage of the function is just as with any other function. |
Afterwards usage of the function is just as with any other function. |
||
Line 702: | Line 702: | ||
libc is already loaded, it is used by Factor elsewhere. |
libc is already loaded, it is used by Factor elsewhere. |
||
< |
<syntaxhighlight lang=factor>FUNCTION: char* strdup ( c-string s ) ; |
||
: my-strdup ( str -- str' ) |
: my-strdup ( str -- str' ) |
||
strdup [ utf8 alien>string ] [ (free) ] bi ;</ |
strdup [ utf8 alien>string ] [ (free) ] bi ;</syntaxhighlight> |
||
( scratchpad ) "abc" my-strdup . |
( scratchpad ) "abc" my-strdup . |
||
Line 782: | Line 782: | ||
Every version of GNU Forth has experimented with a different means to do C foreign function calls. The current implementation resolves various incompatibilities which had plagued earlier mechanisms by parsing C header files and using the host's native toolchain (i.e. gcc and ld) to generate thunks. |
Every version of GNU Forth has experimented with a different means to do C foreign function calls. The current implementation resolves various incompatibilities which had plagued earlier mechanisms by parsing C header files and using the host's native toolchain (i.e. gcc and ld) to generate thunks. |
||
< |
<syntaxhighlight lang=forth>c-library cstrings |
||
\c #include <string.h> |
\c #include <string.h> |
||
Line 804: | Line 804: | ||
duped dup strlen type \ testing |
duped dup strlen type \ testing |
||
duped free throw \ gforth ALLOCATE and FREE map directly to C's malloc() and free()</ |
duped free throw \ gforth ALLOCATE and FREE map directly to C's malloc() and free()</syntaxhighlight> |
||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
Line 815: | Line 815: | ||
Here is an example using the ISO_C_BINDING standard module to link against the C API functions ''strdup'', ''free'' and ''puts''. The program will print two copies of the string ''"Hello, World!"'' using the ''puts'' function. One copy is obtained from ''strdup'', then released with ''free''. The C bindings are placed in an interface module to simplify reuse. The addresses of the two copies are also printed. |
Here is an example using the ISO_C_BINDING standard module to link against the C API functions ''strdup'', ''free'' and ''puts''. The program will print two copies of the string ''"Hello, World!"'' using the ''puts'' function. One copy is obtained from ''strdup'', then released with ''free''. The C bindings are placed in an interface module to simplify reuse. The addresses of the two copies are also printed. |
||
< |
<syntaxhighlight lang=fortran>module c_api |
||
use iso_c_binding |
use iso_c_binding |
||
implicit none |
implicit none |
||
Line 859: | Line 859: | ||
transfer(ptr, 0_c_intptr_t) |
transfer(ptr, 0_c_intptr_t) |
||
call free(ptr) |
call free(ptr) |
||
end program</ |
end program</syntaxhighlight> |
||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
Line 866: | Line 866: | ||
As this uses LocalAlloc in kernel32.dll internally to allocate memory for the duplicated string, we need to call |
As this uses LocalAlloc in kernel32.dll internally to allocate memory for the duplicated string, we need to call |
||
LocalFree to free this memory using the pointer returned by strdup. |
LocalFree to free this memory using the pointer returned by strdup. |
||
< |
<syntaxhighlight lang=freebasic>' FB 1.05.0 Win64 |
||
'Using StrDup function in Shlwapi.dll |
'Using StrDup function in Shlwapi.dll |
||
Line 885: | Line 885: | ||
DyLibFree(library) '' unload first dll |
DyLibFree(library) '' unload first dll |
||
DyLibFree(library2) '' unload second fll |
DyLibFree(library2) '' unload second fll |
||
End</ |
End</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 894: | Line 894: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
Using cgo, part of the standard Go command set. |
Using cgo, part of the standard Go command set. |
||
< |
<syntaxhighlight lang=go>package main |
||
// #include <string.h> |
// #include <string.h> |
||
Line 921: | Line 921: | ||
// demonstrate we have string contents intact |
// demonstrate we have string contents intact |
||
fmt.Println(go2) |
fmt.Println(go2) |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 928: | Line 928: | ||
=={{header|Hare}}== |
=={{header|Hare}}== |
||
< |
<syntaxhighlight lang=hare>// hare run -lc ffi.ha |
||
use fmt; |
use fmt; |
||
Line 943: | Line 943: | ||
fmt::printfln("{}", strings::fromc(dup))!; |
fmt::printfln("{}", strings::fromc(dup))!; |
||
cfree(dup); |
cfree(dup); |
||
};</ |
};</syntaxhighlight> |
||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
< |
<syntaxhighlight lang=Haskell>{-# LANGUAGE ForeignFunctionInterface #-} |
||
import Foreign (free) |
import Foreign (free) |
||
Line 961: | Line 961: | ||
s2_hs <- peekCString s2 -- marshall the C string called s2 into a Haskell string named s2_hs |
s2_hs <- peekCString s2 -- marshall the C string called s2 into a Haskell string named s2_hs |
||
putStrLn s2_hs |
putStrLn s2_hs |
||
free s2) -- s is automatically freed by withCString once done</ |
free s2) -- s is automatically freed by withCString once done</syntaxhighlight> |
||
==Icon and {{header|Unicon}}== |
==Icon and {{header|Unicon}}== |
||
Line 969: | Line 969: | ||
The first step is to create a shared library, to wrap the target C functions and do type conversions on the input and returned values. The arguments to the wrapper functions form a list, and this list must be unpacked to retrieve the arguments to send to the target function. To get at <code>strdup</code> and <code>strcat</code> we would have: |
The first step is to create a shared library, to wrap the target C functions and do type conversions on the input and returned values. The arguments to the wrapper functions form a list, and this list must be unpacked to retrieve the arguments to send to the target function. To get at <code>strdup</code> and <code>strcat</code> we would have: |
||
<syntaxhighlight lang=C> |
|||
<lang C> |
|||
#include <string.h> |
#include <string.h> |
||
#include "icall.h" // a header routine from the Unicon sources - provides helpful type-conversion macros |
#include "icall.h" // a header routine from the Unicon sources - provides helpful type-conversion macros |
||
Line 988: | Line 988: | ||
RetString (result); |
RetString (result); |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
Then the Unicon program must 'access' the function in the shared library: the important step is 'loadfunc' which accesses the named function in the shared library. After that, the C function can be called from within a program: |
Then the Unicon program must 'access' the function in the shared library: the important step is 'loadfunc' which accesses the named function in the shared library. After that, the C function can be called from within a program: |
||
< |
<syntaxhighlight lang=Unicon> |
||
$define LIB "libstrdup-wrapper.so" |
$define LIB "libstrdup-wrapper.so" |
||
Line 1,016: | Line 1,016: | ||
write (strcat ("abc", "def")) |
write (strcat ("abc", "def")) |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
Line 1,029: | Line 1,029: | ||
Here is a windows specific implementation (for relatively recent versions of windows): |
Here is a windows specific implementation (for relatively recent versions of windows): |
||
< |
<syntaxhighlight lang=J>require 'dll' |
||
strdup=: 'msvcrt.dll _strdup >x *' cd < |
strdup=: 'msvcrt.dll _strdup >x *' cd < |
||
free=: 'msvcrt.dll free n x' cd < |
free=: 'msvcrt.dll free n x' cd < |
||
getstr=: free ] memr@,&0 _1</ |
getstr=: free ] memr@,&0 _1</syntaxhighlight> |
||
With these definitions: |
With these definitions: |
||
< |
<syntaxhighlight lang=J> getstr@strdup 'Hello World!' |
||
Hello World!</ |
Hello World!</syntaxhighlight> |
||
Portability is possible, but often irrelevant for a task of this sort. To make this work with a different OS, you would need to use the appropriate file name for libc for the os in question. For example, on linux, replace msvcrt.dll with /lib/libc.so.6 (or whichever version of libc you are using). |
Portability is possible, but often irrelevant for a task of this sort. To make this work with a different OS, you would need to use the appropriate file name for libc for the os in question. For example, on linux, replace msvcrt.dll with /lib/libc.so.6 (or whichever version of libc you are using). |
||
Line 1,048: | Line 1,048: | ||
'''JNIDemo.java''' |
'''JNIDemo.java''' |
||
< |
<syntaxhighlight lang=java>public class JNIDemo |
||
{ |
{ |
||
static |
static |
||
Line 1,059: | Line 1,059: | ||
private static native String callStrdup(String s); |
private static native String callStrdup(String s); |
||
}</ |
}</syntaxhighlight> |
||
Two things to note: First, the "native" stub which will be linked with a native library, and second, the call to System.loadLibrary to actually do the linking at runtime. The class must then be compiled without the native library. |
Two things to note: First, the "native" stub which will be linked with a native library, and second, the call to System.loadLibrary to actually do the linking at runtime. The class must then be compiled without the native library. |
||
Line 1,068: | Line 1,068: | ||
The generated file, '''JNIDemo.h''': |
The generated file, '''JNIDemo.h''': |
||
< |
<syntaxhighlight lang=c>/* DO NOT EDIT THIS FILE - it is machine generated */ |
||
#include <jni.h> |
#include <jni.h> |
||
/* Header for class JNIDemo */ |
/* Header for class JNIDemo */ |
||
Line 1,088: | Line 1,088: | ||
} |
} |
||
#endif |
#endif |
||
#endif</ |
#endif</syntaxhighlight> |
||
Next, the C code which utilizes JNI to bridge between the managed and unmanaged environments. It should include the "h" file, and implement the exported function declared in that file. The specifics of writing JNI code are beyond the scope of this task. |
Next, the C code which utilizes JNI to bridge between the managed and unmanaged environments. It should include the "h" file, and implement the exported function declared in that file. The specifics of writing JNI code are beyond the scope of this task. |
||
'''JNIDemo.c''' |
'''JNIDemo.c''' |
||
< |
<syntaxhighlight lang=c>#include "string.h" |
||
#include "JNIDemo.h" |
#include "JNIDemo.h" |
||
Line 1,136: | Line 1,136: | ||
return dupeString; |
return dupeString; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
In a Windows environment, a dll by the same name should be created ("JNIDemo.dll"). In a Linux environment, a shared object marked executable and with a name preceded by "lib" should be created (in this case, "libJNIDemo.so"). Your compiler will need to know the location of "jni.h", which is in the "include" directory of the JDK. Linux may also need includes that are in the "include/linux" directory. Linux example using gcc: |
In a Windows environment, a dll by the same name should be created ("JNIDemo.dll"). In a Linux environment, a shared object marked executable and with a name preceded by "lib" should be created (in this case, "libJNIDemo.so"). Your compiler will need to know the location of "jni.h", which is in the "include" directory of the JDK. Linux may also need includes that are in the "include/linux" directory. Linux example using gcc: |
||
Line 1,155: | Line 1,155: | ||
'''md5sum.cc''' |
'''md5sum.cc''' |
||
< |
<syntaxhighlight lang=cpp>#include <napi.h> |
||
#include <openssl/md5.h> |
#include <openssl/md5.h> |
||
Line 1,182: | Line 1,182: | ||
} |
} |
||
NODE_API_MODULE(addon, Init)</ |
NODE_API_MODULE(addon, Init)</syntaxhighlight> |
||
Then compile the file with [https://github.com/nodejs/node-gyp node-gyp]. |
Then compile the file with [https://github.com/nodejs/node-gyp node-gyp]. |
||
<lang |
<syntaxhighlight lang=bash>node-gyp build</syntaxhighlight> |
||
Once it has compiled, create the JavaScript bindings. |
Once it has compiled, create the JavaScript bindings. |
||
'''binding.js''' |
'''binding.js''' |
||
< |
<syntaxhighlight lang=javascript>const addon = require('../build/Release/md5sum-native'); |
||
module.exports = addon.md5sum;</ |
module.exports = addon.md5sum;</syntaxhighlight> |
||
Then, you're able to call the function from any Node.js JavaScript file. |
Then, you're able to call the function from any Node.js JavaScript file. |
||
''Using Require:'' |
''Using Require:'' |
||
< |
<syntaxhighlight lang=javascript>const md5sum = require('../lib/binding.js'); |
||
console.log(md5sum('hello'));</ |
console.log(md5sum('hello'));</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,205: | Line 1,205: | ||
'''binding.js''' |
'''binding.js''' |
||
< |
<syntaxhighlight lang=javascript>import { createRequire } from 'module'; |
||
const require = createRequire(import.meta.url); |
const require = createRequire(import.meta.url); |
||
const addon = require('../build/Release/md5sum-native'); |
const addon = require('../build/Release/md5sum-native'); |
||
export default addon.md5sum;</ |
export default addon.md5sum;</syntaxhighlight> |
||
And call the function as follows: |
And call the function as follows: |
||
< |
<syntaxhighlight lang=javascript>import md5sum from '../lib/binding.js'; |
||
console.log(md5sum('hello'));</ |
console.log(md5sum('hello'));</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,223: | Line 1,223: | ||
Julia has a built-in keyword <code>ccall</code> to call external C-like functions. For example: |
Julia has a built-in keyword <code>ccall</code> to call external C-like functions. For example: |
||
< |
<syntaxhighlight lang=julia>p = ccall(:strdup, Ptr{Cuchar}, (Ptr{Cuchar},), "Hello world") |
||
@show unsafe_string(p) # "Hello world" |
@show unsafe_string(p) # "Hello world" |
||
ccall(:free, Void, (Ptr{Cuchar},), p)</ |
ccall(:free, Void, (Ptr{Cuchar},), p)</syntaxhighlight> |
||
'''PyCall''', [https://github.com/JuliaPy/PyCall.jl source]: |
'''PyCall''', [https://github.com/JuliaPy/PyCall.jl source]: |
||
< |
<syntaxhighlight lang=julia>using PyCall |
||
@pyimport math |
@pyimport math |
||
@show math.cos(1) # 0.5403023058681398</ |
@show math.cos(1) # 0.5403023058681398</syntaxhighlight> |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{Works with|Ubuntu|14.04}} |
{{Works with|Ubuntu|14.04}} |
||
< |
<syntaxhighlight lang=scala>// Kotlin Native v0.2 |
||
import kotlinx.cinterop.* |
import kotlinx.cinterop.* |
||
Line 1,242: | Line 1,242: | ||
val hw = strdup ("Hello World!")!!.toKString() |
val hw = strdup ("Hello World!")!!.toKString() |
||
println(hw) |
println(hw) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,255: | Line 1,255: | ||
=={{header|Lisaac}}== |
=={{header|Lisaac}}== |
||
Use backtick notation (`...`) for referencing foreign language (C) features. |
Use backtick notation (`...`) for referencing foreign language (C) features. |
||
< |
<syntaxhighlight lang=Lisaac>Section Header |
||
+ name := TEST_C_INTERFACE; |
+ name := TEST_C_INTERFACE; |
||
Line 1,278: | Line 1,278: | ||
// this will also be inserted in-place, expression type disregarded |
// this will also be inserted in-place, expression type disregarded |
||
`free(@p)`; |
`free(@p)`; |
||
);</ |
);</syntaxhighlight> |
||
=={{header|Locomotive Basic}}== |
=={{header|Locomotive Basic}}== |
||
WinAPE has a built-in Z80 assembler that can copy the assembled program into the Amstrad CPC's memory. Whatever address your <code>org</code> directive was at can be <code>CALL</code>ed in BASIC. |
WinAPE has a built-in Z80 assembler that can copy the assembled program into the Amstrad CPC's memory. Whatever address your <code>org</code> directive was at can be <code>CALL</code>ed in BASIC. |
||
< |
<syntaxhighlight lang=z80>org &1000 |
||
ld a,'A' |
ld a,'A' |
||
call &bb5a |
call &bb5a |
||
ret</ |
ret</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,297: | Line 1,297: | ||
Using the [http://luajit.org/ext_ffi.html FFI library] available in [http://luajit.org/ LuaJIT]: |
Using the [http://luajit.org/ext_ffi.html FFI library] available in [http://luajit.org/ LuaJIT]: |
||
< |
<syntaxhighlight lang=lua>local ffi = require("ffi") |
||
ffi.cdef[[ |
ffi.cdef[[ |
||
char * strndup(const char * s, size_t n); |
char * strndup(const char * s, size_t n); |
||
Line 1,311: | Line 1,311: | ||
print("Copy: " .. s2) |
print("Copy: " .. s2) |
||
print("strlen: " .. ffi.C.strlen(s2)) |
print("strlen: " .. ffi.C.strlen(s2)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Luck}}== |
=={{header|Luck}}== |
||
Line 1,317: | Line 1,317: | ||
Luck supports interfacing with most C libraries out of the box: |
Luck supports interfacing with most C libraries out of the box: |
||
< |
<syntaxhighlight lang=luck>import "stdio.h";; |
||
import "string.h";; |
import "string.h";; |
||
Line 1,323: | Line 1,323: | ||
let s2:char* = strdup(cstring(s1));; |
let s2:char* = strdup(cstring(s1));; |
||
puts(s2);; |
puts(s2);; |
||
free(s2 as void*)</ |
free(s2 as void*)</syntaxhighlight> |
||
=={{header|M2000 Interpreter}}== |
=={{header|M2000 Interpreter}}== |
||
Line 1,329: | Line 1,329: | ||
There is a difference between Windows and Wine implementation of _strdump and swprintf. |
There is a difference between Windows and Wine implementation of _strdump and swprintf. |
||
Value of '''a''' has to hold chars to read from sBuf$ as returned from msvcrt.swprintf, but this can't work in Ubuntu using Wine and in Windows as expected, so we can use '''LeftPart$(string, string as delimiter sign not included as result)''' |
Value of '''a''' has to hold chars to read from sBuf$ as returned from msvcrt.swprintf, but this can't work in Ubuntu using Wine and in Windows as expected, so we can use '''LeftPart$(string, string as delimiter sign not included as result)''' |
||
< |
<syntaxhighlight lang=M2000 Interpreter> |
||
Module CheckCCall { |
Module CheckCCall { |
||
Line 1,352: | Line 1,352: | ||
} |
} |
||
CheckCCall |
CheckCCall |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
Line 1,360: | Line 1,360: | ||
===Call VbScript=== |
===Call VbScript=== |
||
< |
<syntaxhighlight lang=M2000 Interpreter> |
||
Module Checkit { |
Module Checkit { |
||
Global a() |
Global a() |
||
Line 1,404: | Line 1,404: | ||
} |
} |
||
CheckIt |
CheckIt |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Call Javascript=== |
===Call Javascript=== |
||
< |
<syntaxhighlight lang=M2000 Interpreter> |
||
Module CheckJavaScript { |
Module CheckJavaScript { |
||
Clear |
Clear |
||
Line 1,461: | Line 1,461: | ||
} |
} |
||
CheckJavaScript |
CheckJavaScript |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Call A System Function (Win32)=== |
===Call A System Function (Win32)=== |
||
< |
<syntaxhighlight lang=M2000 Interpreter> |
||
Declare MessageBox Lib "user32.MessageBoxW" {long alfa, lptext$, lpcaption$, long type} |
Declare MessageBox Lib "user32.MessageBoxW" {long alfa, lptext$, lpcaption$, long type} |
||
Print MessageBox(Hwnd, "HELLO THERE", "GEORGE", 2) |
Print MessageBox(Hwnd, "HELLO THERE", "GEORGE", 2) |
||
Remove "user32" |
Remove "user32" |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Make, use and remove a C Dll at runtime=== |
===Make, use and remove a C Dll at runtime=== |
||
H C dll to produce an array of primes. We can |
H C dll to produce an array of primes. We can |
||
< |
<syntaxhighlight lang=M2000 Interpreter> |
||
Module checkit { |
Module checkit { |
||
Static DisplayOnce=0 |
Static DisplayOnce=0 |
||
Line 1,599: | Line 1,599: | ||
checkit |
checkit |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Maple}}== |
=={{header|Maple}}== |
||
We can call strdup, as requested, in the following way |
We can call strdup, as requested, in the following way |
||
< |
<syntaxhighlight lang=Maple>> strdup := define_external( strdup, s::string, RETURN::string, LIB = "/lib/libc.so.6" ): |
||
> strdup( "foo" ); |
> strdup( "foo" ); |
||
"foo" |
"foo" |
||
</syntaxhighlight> |
|||
</lang> |
|||
However, this doesn't make a lot of sense in Maple, since there can be only one copy of any Maple string in memory. Moreover, I don't see any easy way to free the memory allocated by strdup. A more sensible example for Maple follows. (It might be sensible if you wanted to compare your system library version of sin with the one built-in to Maple, for instance.) |
However, this doesn't make a lot of sense in Maple, since there can be only one copy of any Maple string in memory. Moreover, I don't see any easy way to free the memory allocated by strdup. A more sensible example for Maple follows. (It might be sensible if you wanted to compare your system library version of sin with the one built-in to Maple, for instance.) |
||
< |
<syntaxhighlight lang=Maple>> csin := define_external( sin, s::float[8], RETURN::float[8], LIB = "libm.so" ); |
||
csin := proc(s::numeric) |
csin := proc(s::numeric) |
||
option call_external, define_external(sin, s::float[8], |
option call_external, define_external(sin, s::float[8], |
||
Line 1,618: | Line 1,618: | ||
> csin( evalf( Pi / 2 ) ); |
> csin( evalf( Pi / 2 ) ); |
||
1.</ |
1.</syntaxhighlight> |
||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
This works on windows and on linux/mac (through Mono) |
This works on windows and on linux/mac (through Mono) |
||
< |
<syntaxhighlight lang=Mathematica>Needs["NETLink`"]; |
||
externalstrdup = DefineDLLFunction["_strdup", "msvcrt.dll", "string", {"string"}]; |
externalstrdup = DefineDLLFunction["_strdup", "msvcrt.dll", "string", {"string"}]; |
||
Print["Duplicate: ", externalstrdup["Hello world!"]]</ |
Print["Duplicate: ", externalstrdup["Hello world!"]]</syntaxhighlight> |
||
output |
output |
||
<pre>Duplicate: Hello world!</pre> |
<pre>Duplicate: Hello world!</pre> |
||
Line 1,630: | Line 1,630: | ||
=={{header|Maxima}}== |
=={{header|Maxima}}== |
||
< |
<syntaxhighlight lang=maxima>/* Maxima is written in Lisp and can call Lisp functions. |
||
Use load("funcs.lisp"), or inside Maxima: */ |
Use load("funcs.lisp"), or inside Maxima: */ |
||
Line 1,638: | Line 1,638: | ||
f(5, 6); |
f(5, 6); |
||
11</ |
11</syntaxhighlight> |
||
=={{header|Mercury}}== |
=={{header|Mercury}}== |
||
Line 1,644: | Line 1,644: | ||
Mercury is designed to interact sensibly with foreign code, even while keeping itself as pure and as safe as is possible in such circumstances. Here is an example of calling C's strdup() function from within Mercury: |
Mercury is designed to interact sensibly with foreign code, even while keeping itself as pure and as safe as is possible in such circumstances. Here is an example of calling C's strdup() function from within Mercury: |
||
< |
<syntaxhighlight lang=mercury>:- module test_ffi. |
||
:- interface. |
:- interface. |
||
Line 1,666: | Line 1,666: | ||
io.write_string(strdup("Hello, worlds!\n"), !IO). |
io.write_string(strdup("Hello, worlds!\n"), !IO). |
||
:- end_module test_ffi.</ |
:- end_module test_ffi.</syntaxhighlight> |
||
Only the lines wrapped in comments matter for this. The rest is an application skeleton so this can be compiled and tested. |
Only the lines wrapped in comments matter for this. The rest is an application skeleton so this can be compiled and tested. |
||
Line 1,674: | Line 1,674: | ||
After this the Mercury strdup/1 function itself is declared. For purposes of exposition it has been declared fully with types and modes. The modes, however, are redundant since by default functions in Mercury have all input parameters and an output return value. Also, the determinism is declared which is again redundant. By default Mercury functions are deterministic. That line could easily have been written thusly instead: |
After this the Mercury strdup/1 function itself is declared. For purposes of exposition it has been declared fully with types and modes. The modes, however, are redundant since by default functions in Mercury have all input parameters and an output return value. Also, the determinism is declared which is again redundant. By default Mercury functions are deterministic. That line could easily have been written thusly instead: |
||
< |
<syntaxhighlight lang=mercury>:- func strdup(string) = string.</syntaxhighlight> |
||
The next block of code is the foreign_proc pragma declaration. In this declaration the language ("C") is declared, the footprint of the function is again provided, this time with variable names and modes but without the determinism, a set of properties is declared and the actual C code to be executed is provided. This last piece is trivial, but the properties themselves are worth looking more closely at. |
The next block of code is the foreign_proc pragma declaration. In this declaration the language ("C") is declared, the footprint of the function is again provided, this time with variable names and modes but without the determinism, a set of properties is declared and the actual C code to be executed is provided. This last piece is trivial, but the properties themselves are worth looking more closely at. |
||
Line 1,684: | Line 1,684: | ||
=={{header|Modula-2}}== |
=={{header|Modula-2}}== |
||
The first file (Vga.c) creates the function prototypes. |
The first file (Vga.c) creates the function prototypes. |
||
< |
<syntaxhighlight lang=c>#include <vga.h> |
||
int Initialize (void) |
int Initialize (void) |
||
Line 1,751: | Line 1,751: | ||
{ |
{ |
||
*ch = vga_getkey (); |
*ch = vga_getkey (); |
||
}</ |
}</syntaxhighlight> |
||
The next file is the definition module, but in this context it is called a '''FOREIGN MODULE'''. |
The next file is the definition module, but in this context it is called a '''FOREIGN MODULE'''. |
||
< |
<syntaxhighlight lang=modula2>FOREIGN MODULE Vga; |
||
TYPE EGAcolour = (black, blue, green, cyan, red, pink, brown, white, |
TYPE EGAcolour = (black, blue, green, cyan, red, pink, brown, white, |
||
Line 1,784: | Line 1,784: | ||
PROCEDURE GetKey (VAR ch : CHAR); |
PROCEDURE GetKey (VAR ch : CHAR); |
||
END Vga.</ |
END Vga.</syntaxhighlight> |
||
The third file is an example program. |
The third file is an example program. |
||
< |
<syntaxhighlight lang=modula2>MODULE svg01; |
||
FROM InOut IMPORT Read, Write, WriteBf, WriteString; |
FROM InOut IMPORT Read, Write, WriteBf, WriteString; |
||
Line 1,818: | Line 1,818: | ||
Write (ch); |
Write (ch); |
||
WriteBf; |
WriteBf; |
||
END svg01.</ |
END svg01.</syntaxhighlight> |
||
=={{header|Modula-3}}== |
=={{header|Modula-3}}== |
||
Modula-3 provides many predefined interfaces to C files. Here we use <tt>Cstring</tt> which uses C string functions. Note we have to convert strings of type <tt>TEXT</tt> into C strings (NULL terminated character arrays). Also note the code requires the <tt>UNSAFE</tt> keyword because it interfaces with C (which is unsafe). |
Modula-3 provides many predefined interfaces to C files. Here we use <tt>Cstring</tt> which uses C string functions. Note we have to convert strings of type <tt>TEXT</tt> into C strings (NULL terminated character arrays). Also note the code requires the <tt>UNSAFE</tt> keyword because it interfaces with C (which is unsafe). |
||
< |
<syntaxhighlight lang=modula3>UNSAFE MODULE Foreign EXPORTS Main; |
||
IMPORT IO, Ctypes, Cstring, M3toC; |
IMPORT IO, Ctypes, Cstring, M3toC; |
||
Line 1,838: | Line 1,838: | ||
M3toC.FreeCopiedS(string1); |
M3toC.FreeCopiedS(string1); |
||
M3toC.FreeCopiedS(string2); |
M3toC.FreeCopiedS(string2); |
||
END Foreign.</ |
END Foreign.</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,845: | Line 1,845: | ||
=={{header|Mosaic}}== |
=={{header|Mosaic}}== |
||
< |
<syntaxhighlight lang=mosaic>import clib |
||
importdll msvcrt = |
importdll msvcrt = |
||
Line 1,856: | Line 1,856: | ||
str2:=_strdup(&.str) |
str2:=_strdup(&.str) |
||
println str2 |
println str2 |
||
end</ |
end</syntaxhighlight> |
||
=={{header|Never}}== |
=={{header|Never}}== |
||
Never includes libffi for access to foreign functions, but currently only supports very basic types, int, float, string. ''strdup'' will work, but the ''voidness'' of ''free'' is not yet supported. This solution uses some of the Math functions in libm instead. |
Never includes libffi for access to foreign functions, but currently only supports very basic types, int, float, string. ''strdup'' will work, but the ''voidness'' of ''free'' is not yet supported. This solution uses some of the Math functions in libm instead. |
||
< |
<syntaxhighlight lang=fsharp>extern "libm.so.6" func sinhf(x : float) -> float |
||
extern "libm.so.6" func coshf(x : float) -> float |
extern "libm.so.6" func coshf(x : float) -> float |
||
extern "libm.so.6" func powf(base : float, exp : float) -> float |
extern "libm.so.6" func powf(base : float, exp : float) -> float |
||
Line 1,880: | Line 1,880: | ||
0 |
0 |
||
}</ |
}</syntaxhighlight> |
||
Line 1,895: | Line 1,895: | ||
newLISP has two FFI APIs. The simple API needs no type specifiers but is limited to integers and pointers. |
newLISP has two FFI APIs. The simple API needs no type specifiers but is limited to integers and pointers. |
||
The extended API can specify types for return values and parameters and can also be used for floats and structs. |
The extended API can specify types for return values and parameters and can also be used for floats and structs. |
||
< |
<syntaxhighlight lang=NewLISP>; simple FFI interface on Mac OSX |
||
(import "libc.dylib" "strdup") |
(import "libc.dylib" "strdup") |
||
(println (get-string (strdup "hello world"))) |
(println (get-string (strdup "hello world"))) |
||
Line 1,902: | Line 1,902: | ||
(import "libc.dylib" "strdup" "char*" "char*") |
(import "libc.dylib" "strdup" "char*" "char*") |
||
(println (strdup "hello world")) |
(println (strdup "hello world")) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
Since Nim compiles to C by default, this task is easily done: |
Since Nim compiles to C by default, this task is easily done: |
||
< |
<syntaxhighlight lang=nim>proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.} |
||
echo strcmp("abc", "def") |
echo strcmp("abc", "def") |
||
echo strcmp("hello", "hello") |
echo strcmp("hello", "hello") |
||
Line 1,914: | Line 1,914: | ||
var x = "foo" |
var x = "foo" |
||
printf("Hello %d %s!\n", 12, x)</ |
printf("Hello %d %s!\n", 12, x)</syntaxhighlight> |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
Line 1,920: | Line 1,920: | ||
===Outline of what is linked against=== |
===Outline of what is linked against=== |
||
For the hypothetical [[C]] library that contains functions described by a header file with this in: |
For the hypothetical [[C]] library that contains functions described by a header file with this in: |
||
< |
<syntaxhighlight lang=ocaml>void myfunc_a(); |
||
float myfunc_b(int, float); |
float myfunc_b(int, float); |
||
char *myfunc_c(int *, int);</ |
char *myfunc_c(int *, int);</syntaxhighlight> |
||
The header file is named "<tt>mylib.h</tt>", and linked against the library with <tt>-lmylib</tt> and compiled with <tt>-I/usr/include/mylib</tt>. |
The header file is named "<tt>mylib.h</tt>", and linked against the library with <tt>-lmylib</tt> and compiled with <tt>-I/usr/include/mylib</tt>. |
||
Line 1,929: | Line 1,929: | ||
====file "mylib.ml":==== |
====file "mylib.ml":==== |
||
< |
<syntaxhighlight lang=ocaml>external myfunc_a: unit -> unit = "caml_myfunc_a" |
||
external myfunc_b: int -> float -> float = "caml_myfunc_b" |
external myfunc_b: int -> float -> float = "caml_myfunc_b" |
||
external myfunc_c: int array -> string = "caml_myfunc_c"</ |
external myfunc_c: int array -> string = "caml_myfunc_c"</syntaxhighlight> |
||
====file "wrap_mylib.c":==== |
====file "wrap_mylib.c":==== |
||
< |
<syntaxhighlight lang=c>#include <caml/mlvalues.h> |
||
#include <caml/alloc.h> |
#include <caml/alloc.h> |
||
#include <mylib.h> |
#include <mylib.h> |
||
Line 1,963: | Line 1,963: | ||
free(arr); |
free(arr); |
||
return caml_copy_string(s); |
return caml_copy_string(s); |
||
}</ |
}</syntaxhighlight> |
||
====the Makefile:==== |
====the Makefile:==== |
||
(replace spaces by tabs) |
(replace spaces by tabs) |
||
< |
<syntaxhighlight lang=makefile>wrap_mylib.o: wrap_mylib.c |
||
ocamlc -c -ccopt -I/usr/include/mylib $< |
ocamlc -c -ccopt -I/usr/include/mylib $< |
||
Line 1,992: | Line 1,992: | ||
clean: |
clean: |
||
rm -f *.[oa] *.so *.cm[ixoa] *.cmxa</ |
rm -f *.[oa] *.so *.cm[ixoa] *.cmxa</syntaxhighlight> |
||
the file <tt>mylib.cma</tt> is used for the interpreted and bytecode modes, and <tt>mylib.cmxa</tt> is for the native mode. |
the file <tt>mylib.cma</tt> is used for the interpreted and bytecode modes, and <tt>mylib.cmxa</tt> is for the native mode. |
||
Line 2,001: | Line 2,001: | ||
There is another solution for calling C functions from a C library which is to use '''ocaml-ctypes'''. We can then define bindings by writing only OCaml code without any C stubs. The equivalent for wrapping the previous hypothetical [[C]] library will be: |
There is another solution for calling C functions from a C library which is to use '''ocaml-ctypes'''. We can then define bindings by writing only OCaml code without any C stubs. The equivalent for wrapping the previous hypothetical [[C]] library will be: |
||
< |
<syntaxhighlight lang=ocaml>open Ctypes |
||
open Foreign |
open Foreign |
||
Line 2,011: | Line 2,011: | ||
let arr = CArray.of_list int lst in |
let arr = CArray.of_list int lst in |
||
myfunc_c (to_voidp (CArray.start arr)) (CArray.length arr) |
myfunc_c (to_voidp (CArray.start arr)) (CArray.length arr) |
||
;;</ |
;;</syntaxhighlight> |
||
=={{header|Ol}}== |
=={{header|Ol}}== |
||
< |
<syntaxhighlight lang=scheme> |
||
(import (otus ffi)) |
(import (otus ffi)) |
||
Line 2,021: | Line 2,021: | ||
(print (strdup "Hello World!")) |
(print (strdup "Hello World!")) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Windows has no a "strdup" function, so windows version should look like this. |
Windows has no a "strdup" function, so windows version should look like this. |
||
< |
<syntaxhighlight lang=scheme> |
||
(import (otus ffi)) |
(import (otus ffi)) |
||
Line 2,034: | Line 2,034: | ||
(print (strdup "Hello World!")) |
(print (strdup "Hello World!")) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Note: this simplest way is not freeing allocated by "strdup" function string. |
Note: this simplest way is not freeing allocated by "strdup" function string. |
||
Ol provides a way to call ol functions directly from native code (means callbacks). |
Ol provides a way to call ol functions directly from native code (means callbacks). |
||
< |
<syntaxhighlight lang=scheme> |
||
; The sample usage of GTK3+ library |
; The sample usage of GTK3+ library |
||
(import (otus ffi) |
(import (otus ffi) |
||
Line 2,074: | Line 2,074: | ||
(g_application_run app 0 #false) |
(g_application_run app 0 #false) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Oz}}== |
=={{header|Oz}}== |
||
First we need to create a so-called "native functor" that converts the arguments and describes the C functions: |
First we need to create a so-called "native functor" that converts the arguments and describes the C functions: |
||
< |
<syntaxhighlight lang=cpp>#include "mozart.h" |
||
#include <string.h> |
#include <string.h> |
||
Line 2,098: | Line 2,098: | ||
}; |
}; |
||
return table; |
return table; |
||
}</ |
}</syntaxhighlight> |
||
Save this file as "strdup.cc". To automate compiling and linking, we need a makefile for <code>ozmake</code>, the Oz build tool. Save this file as "makefile.oz": |
Save this file as "strdup.cc". To automate compiling and linking, we need a makefile for <code>ozmake</code>, the Oz build tool. Save this file as "makefile.oz": |
||
< |
<syntaxhighlight lang=oz>makefile( |
||
lib : [ |
lib : [ |
||
'strdup.o' 'strdup.so' |
'strdup.o' 'strdup.so' |
||
] |
] |
||
rules:o('strdup.so':ld('strdup.o')) |
rules:o('strdup.so':ld('strdup.o')) |
||
)</ |
)</syntaxhighlight> |
||
Call <code>ozmake</code> in the same directory. |
Call <code>ozmake</code> in the same directory. |
||
Now we can write some code that uses the wrapped C function (make sure Emacs' working directory is set to the same directory): |
Now we can write some code that uses the wrapped C function (make sure Emacs' working directory is set to the same directory): |
||
< |
<syntaxhighlight lang=oz>declare |
||
[Strdup] = {Module.link ['strdup.so{native}']} |
[Strdup] = {Module.link ['strdup.so{native}']} |
||
in |
in |
||
{System.showInfo {Strdup.strdup "hello"}}</ |
{System.showInfo {Strdup.strdup "hello"}}</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Line 2,124: | Line 2,124: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
Perl code calls a C function <code>c_dup()</code> passing a string <code>'Hello'</code> as an argument, which gets transparently converted to a C string, the <code>c_dup()</code> function makes a copy of that string using <code>strdup()</code> function, stores pointer to the copy in the <code>copy</code> variable and returns it. The returned <code>char</code> pointer gets converted transparently to a Perl string value and gets returned to the calling Perl code which prints it. Then the Perl code calls a C function <code>c_free()</code> to free the allocated memory. Both of the C functions are defined inline in the Perl program and are automatically compiled (only once, unless they change) and linked at runtime. Here is the entire program: |
Perl code calls a C function <code>c_dup()</code> passing a string <code>'Hello'</code> as an argument, which gets transparently converted to a C string, the <code>c_dup()</code> function makes a copy of that string using <code>strdup()</code> function, stores pointer to the copy in the <code>copy</code> variable and returns it. The returned <code>char</code> pointer gets converted transparently to a Perl string value and gets returned to the calling Perl code which prints it. Then the Perl code calls a C function <code>c_free()</code> to free the allocated memory. Both of the C functions are defined inline in the Perl program and are automatically compiled (only once, unless they change) and linked at runtime. Here is the entire program: |
||
< |
<syntaxhighlight lang=perl>use Inline C => q{ |
||
char *copy; |
char *copy; |
||
char * c_dup(char *orig) { |
char * c_dup(char *orig) { |
||
Line 2,134: | Line 2,134: | ||
}; |
}; |
||
print c_dup('Hello'), "\n"; |
print c_dup('Hello'), "\n"; |
||
c_free();</ |
c_free();</syntaxhighlight> |
||
Another example, instead of returning the copy to Perl code it prints it using C printf: |
Another example, instead of returning the copy to Perl code it prints it using C printf: |
||
< |
<syntaxhighlight lang=perl>use Inline C => q{ |
||
void c_hello (char *text) { |
void c_hello (char *text) { |
||
char *copy = strdup(text); |
char *copy = strdup(text); |
||
Line 2,144: | Line 2,144: | ||
} |
} |
||
}; |
}; |
||
c_hello 'world';</ |
c_hello 'world';</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 2,151: | Line 2,151: | ||
a library component which can be re-used in different applications.<br> |
a library component which can be re-used in different applications.<br> |
||
See also builtins/cffi.e, a text-based C interface that handles C-style structs, unions, and function declarations directly. |
See also builtins/cffi.e, a text-based C interface that handles C-style structs, unions, and function declarations directly. |
||
<!--< |
<!--<syntaxhighlight lang=Phix>(notonline)--> |
||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- not from a browser, mate!</span> |
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- not from a browser, mate!</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #000000;">shlwapi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_dll</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"shlwapi.dll"</span><span style="color: #0000FF;">),</span> |
<span style="color: #008080;">constant</span> <span style="color: #000000;">shlwapi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_dll</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"shlwapi.dll"</span><span style="color: #0000FF;">),</span> |
||
Line 2,162: | Line 2,162: | ||
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">peek_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pMem</span><span style="color: #0000FF;">)</span> |
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">peek_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pMem</span><span style="color: #0000FF;">)</span> |
||
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xLocalFree</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">pMem</span><span style="color: #0000FF;">})==</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span> |
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xLocalFree</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">pMem</span><span style="color: #0000FF;">})==</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,177: | Line 2,177: | ||
===32-bit version=== |
===32-bit version=== |
||
< |
<syntaxhighlight lang=PicoLisp>(load "@lib/gcc.l") |
||
(gcc "str" NIL # The 'gcc' function passes all text |
(gcc "str" NIL # The 'gcc' function passes all text |
||
Line 2,195: | Line 2,195: | ||
/**/ |
/**/ |
||
(println 'Duplicate (duptest "Hello world!"))</ |
(println 'Duplicate (duptest "Hello world!"))</syntaxhighlight> |
||
===64-bit version=== |
===64-bit version=== |
||
<syntaxhighlight lang=C> |
|||
<lang C> |
|||
/* |
/* |
||
How to create the shared lib/so file: |
How to create the shared lib/so file: |
||
Line 2,218: | Line 2,218: | ||
int main() { |
int main() { |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
< |
<syntaxhighlight lang=PicoLisp> |
||
(prinl "Calling custom so/dll library...") |
(prinl "Calling custom so/dll library...") |
||
(set 'A NIL) |
(set 'A NIL) |
||
Line 2,226: | Line 2,226: | ||
(prinl "A=" A) |
(prinl "A=" A) |
||
(when (not (= A NIL)) (prinl "Success!")) |
(when (not (= A NIL)) (prinl "Success!")) |
||
</syntaxhighlight> |
|||
</lang> |
|||
<out> |
<out> |
||
Line 2,237: | Line 2,237: | ||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
<lang>declare strdup entry (character (30) varyingz) options (fastcall16); |
<syntaxhighlight lang=text>declare strdup entry (character (30) varyingz) options (fastcall16); |
||
put (strdup('hello world') );</ |
put (strdup('hello world') );</syntaxhighlight> |
||
=={{header|Prolog}}== |
=={{header|Prolog}}== |
||
In SWI-Prolog we need to do two things. First we need to declare a mapping from a Prolog file to a C implementation: |
In SWI-Prolog we need to do two things. First we need to declare a mapping from a Prolog file to a C implementation: |
||
< |
<syntaxhighlight lang=prolog>:- module(plffi, [strdup/2]). |
||
:- use_foreign_library(plffi).</ |
:- use_foreign_library(plffi).</syntaxhighlight> |
||
This declares a module "plffi" that exports the '''predicate''' (''not'' function!) "strdup/2". This predicate has two arguments: the first being the atom being strduped, the second being the duped atom. (You can think of these as an in parameter and an out parameter and be about 2/3 right.) |
This declares a module "plffi" that exports the '''predicate''' (''not'' function!) "strdup/2". This predicate has two arguments: the first being the atom being strduped, the second being the duped atom. (You can think of these as an in parameter and an out parameter and be about 2/3 right.) |
||
Line 2,251: | Line 2,251: | ||
Then we need to write a C file that gives us the interface to the underlying C function (strdup in this case), mapping the ''predicate''' call to a C '''function''' call: |
Then we need to write a C file that gives us the interface to the underlying C function (strdup in this case), mapping the ''predicate''' call to a C '''function''' call: |
||
< |
<syntaxhighlight lang=c>#include <string.h> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <SWI-Prolog.h> |
#include <SWI-Prolog.h> |
||
Line 2,270: | Line 2,270: | ||
{ |
{ |
||
PL_register_foreign("strdup", 2, pl_strdup, 0); |
PL_register_foreign("strdup", 2, pl_strdup, 0); |
||
}</ |
}</syntaxhighlight> |
||
This C code provides us with two things. The function install_plffi() is provided to register the name "strdup" and to map it to its C implementation pl_strdup(). Here we're saying that "strdup" has an arity of 2, is implemented by pl_strdup and has no special flags. |
This C code provides us with two things. The function install_plffi() is provided to register the name "strdup" and to map it to its C implementation pl_strdup(). Here we're saying that "strdup" has an arity of 2, is implemented by pl_strdup and has no special flags. |
||
Line 2,278: | Line 2,278: | ||
We compile this very easily: |
We compile this very easily: |
||
< |
<syntaxhighlight lang=sh>$ swipl-ld -o plffi -shared plffi.c</syntaxhighlight> |
||
Then, from within the SWI-Prolog interactor: |
Then, from within the SWI-Prolog interactor: |
||
< |
<syntaxhighlight lang=Prolog>?- [plffi]. |
||
% plffi compiled into plffi 0.04 sec, 1,477 clauses |
% plffi compiled into plffi 0.04 sec, 1,477 clauses |
||
true. |
true. |
||
Line 2,296: | Line 2,296: | ||
?- X = booger, strdup(booger, X). |
?- X = booger, strdup(booger, X). |
||
X = booger.</ |
X = booger.</syntaxhighlight> |
||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
Line 2,303: | Line 2,303: | ||
the resulting executable. [http://www.purebasic.com/ PureBasic] supports {Windows, Linux, MacOS}. |
the resulting executable. [http://www.purebasic.com/ PureBasic] supports {Windows, Linux, MacOS}. |
||
< |
<syntaxhighlight lang=PureBasic> |
||
; Call_a_foreign_language_function.fasm -> Call_a_foreign_language_function.obj |
; Call_a_foreign_language_function.fasm -> Call_a_foreign_language_function.obj |
||
; the assembler code... |
; the assembler code... |
||
Line 2,343: | Line 2,343: | ||
public strucase as "_strucase@4" |
public strucase as "_strucase@4" |
||
</syntaxhighlight> |
|||
</lang> |
|||
< |
<syntaxhighlight lang=PureBasic> |
||
; the PureBasic code... |
; the PureBasic code... |
||
Line 2,356: | Line 2,356: | ||
; cw(peeks(*r)) |
; cw(peeks(*r)) |
||
Debug peeks(*r) |
Debug peeks(*r) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Line 2,366: | Line 2,366: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang=python>import ctypes |
||
libc = ctypes.CDLL("/lib/libc.so.6") |
libc = ctypes.CDLL("/lib/libc.so.6") |
||
libc.strcmp("abc", "def") # -1 |
libc.strcmp("abc", "def") # -1 |
||
libc.strcmp("hello", "hello") # 0</ |
libc.strcmp("hello", "hello") # 0</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang=racket> |
||
#lang racket/base |
#lang racket/base |
||
(require ffi/unsafe) |
(require ffi/unsafe) |
||
Line 2,414: | Line 2,414: | ||
;; Let's try it: |
;; Let's try it: |
||
(strdup "Hello World!") |
(strdup "Hello World!") |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
{{Works with|rakudo|2016.07}} |
{{Works with|rakudo|2016.07}} |
||
<lang |
<syntaxhighlight lang=raku line>use NativeCall; |
||
sub strdup(Str $s --> Pointer) is native {*} |
sub strdup(Str $s --> Pointer) is native {*} |
||
Line 2,427: | Line 2,427: | ||
my $p = strdup("Success!"); |
my $p = strdup("Success!"); |
||
say 'puts returns ', puts($p); |
say 'puts returns ', puts($p); |
||
say 'free returns ', free($p);</ |
say 'free returns ', free($p);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Success! |
<pre>Success! |
||
Line 2,434: | Line 2,434: | ||
=={{header|REALbasic}}== |
=={{header|REALbasic}}== |
||
<syntaxhighlight lang=vb> |
|||
<lang vb> |
|||
Declare Function CreateFileW Lib "Kernel32" (FileName As WString, DesiredAccess As Integer, ShareMode As Integer, SecurityAttributes As Integer, _ |
Declare Function CreateFileW Lib "Kernel32" (FileName As WString, DesiredAccess As Integer, ShareMode As Integer, SecurityAttributes As Integer, _ |
||
CreateDisposition As Integer, Flags As Integer, Template As Integer) As Integer |
CreateDisposition As Integer, Flags As Integer, Template As Integer) As Integer |
||
Line 2,457: | Line 2,457: | ||
MsgBox("Error Number: " + Str(GetLastError)) |
MsgBox("Error Number: " + Str(GetLastError)) |
||
End If |
End If |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
The use of the '''address''' statement isn't normally required, but it's shown here as an illustrative example. |
The use of the '''address''' statement isn't normally required, but it's shown here as an illustrative example. |
||
< |
<syntaxhighlight lang=rexx>/*REXX program calls (invoke) a "foreign" (non-REXX) language routine/program. */ |
||
cmd = "MODE" /*define the command that is to be used*/ |
cmd = "MODE" /*define the command that is to be used*/ |
||
Line 2,468: | Line 2,468: | ||
address 'SYSTEM' cmd opts /*invoke a cmd via the SYSTEM interface*/ |
address 'SYSTEM' cmd opts /*invoke a cmd via the SYSTEM interface*/ |
||
/*stick a fork in it, we're all done. */</ |
/*stick a fork in it, we're all done. */</syntaxhighlight> |
||
{{out|output|text= when executing under a Microsoft Windows system in the USA, code pages vary upon the country:}} |
{{out|output|text= when executing under a Microsoft Windows system in the USA, code pages vary upon the country:}} |
||
<pre> |
<pre> |
||
Line 2,487: | Line 2,487: | ||
{{works with|MRI}} |
{{works with|MRI}} |
||
< |
<syntaxhighlight lang=c>/* rc_strdup.c */ |
||
#include <stdlib.h> /* free() */ |
#include <stdlib.h> /* free() */ |
||
#include <string.h> /* strdup() */ |
#include <string.h> /* strdup() */ |
||
Line 2,520: | Line 2,520: | ||
VALUE mRosettaCode = rb_define_module("RosettaCode"); |
VALUE mRosettaCode = rb_define_module("RosettaCode"); |
||
rb_define_module_function(mRosettaCode, "strdup", rc_strdup, 1); |
rb_define_module_function(mRosettaCode, "strdup", rc_strdup, 1); |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang=ruby># extconf.rb |
||
require 'mkmf' |
require 'mkmf' |
||
create_makefile('rc_strdup')</ |
create_makefile('rc_strdup')</syntaxhighlight> |
||
< |
<syntaxhighlight lang=ruby># demo.rb |
||
require 'rc_strdup' |
require 'rc_strdup' |
||
puts RosettaCode.strdup('This string gets duplicated.')</ |
puts RosettaCode.strdup('This string gets duplicated.')</syntaxhighlight> |
||
=== FFI === |
=== FFI === |
||
Line 2,534: | Line 2,534: | ||
A recent effort to make it easier to write libraries, portable across platforms and interpreters, led to the creation of a [http://sourceware.org/libffi/ libffi] binding simply called [http://wiki.github.com/ffi/ffi/ ffi] for completely dynamic calls. |
A recent effort to make it easier to write libraries, portable across platforms and interpreters, led to the creation of a [http://sourceware.org/libffi/ libffi] binding simply called [http://wiki.github.com/ffi/ffi/ ffi] for completely dynamic calls. |
||
< |
<syntaxhighlight lang=ruby> |
||
require 'ffi' |
require 'ffi' |
||
Line 2,549: | Line 2,549: | ||
puts duplicate.get_string(0) |
puts duplicate.get_string(0) |
||
LibC.free(duplicate) |
LibC.free(duplicate) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Line 2,557: | Line 2,557: | ||
{{works with|Ruby|2.0+}} |
{{works with|Ruby|2.0+}} |
||
< |
<syntaxhighlight lang=ruby>require 'fiddle' |
||
# Find strdup(). It takes a pointer and returns a pointer. |
# Find strdup(). It takes a pointer and returns a pointer. |
||
Line 2,569: | Line 2,569: | ||
duplicate = strdup.call("This is a string!") |
duplicate = strdup.call("This is a string!") |
||
puts duplicate.to_s # Convert the C string to a Ruby string. |
puts duplicate.to_s # Convert the C string to a Ruby string. |
||
Fiddle.free duplicate # free() the memory that strdup() allocated.</ |
Fiddle.free duplicate # free() the memory that strdup() allocated.</syntaxhighlight> |
||
Fiddle::Importer is also part of Ruby's standard library. |
Fiddle::Importer is also part of Ruby's standard library. |
||
{{works with|Ruby|2.0+}} |
{{works with|Ruby|2.0+}} |
||
< |
<syntaxhighlight lang=ruby>require 'fiddle' |
||
require 'fiddle/import' |
require 'fiddle/import' |
||
Line 2,585: | Line 2,585: | ||
duplicate = C.strdup("This is a string!") |
duplicate = C.strdup("This is a string!") |
||
puts duplicate.to_s |
puts duplicate.to_s |
||
Fiddle.free duplicate</ |
Fiddle.free duplicate</syntaxhighlight> |
||
=== RubyInline === |
=== RubyInline === |
||
Line 2,591: | Line 2,591: | ||
Using {{libheader|RubyGems}} package [http://www.zenspider.com/ZSS/Products/RubyInline/ RubyInline], which compiles the inlined code on demand during runtime. |
Using {{libheader|RubyGems}} package [http://www.zenspider.com/ZSS/Products/RubyInline/ RubyInline], which compiles the inlined code on demand during runtime. |
||
< |
<syntaxhighlight lang=ruby>require 'rubygems' |
||
require 'inline' |
require 'inline' |
||
Line 2,623: | Line 2,623: | ||
t = InlineTester.new |
t = InlineTester.new |
||
11.upto(14) {|n| p [n, t.factorial_ruby(n), t.factorial_c(n)]} |
11.upto(14) {|n| p [n, t.factorial_ruby(n), t.factorial_c(n)]} |
||
p t.my_ilogb(1000)</ |
p t.my_ilogb(1000)</syntaxhighlight> |
||
outputs (note Ruby's implicit use of Bignum past 12!, while C is stuck with a long int): |
outputs (note Ruby's implicit use of Bignum past 12!, while C is stuck with a long int): |
||
Line 2,634: | Line 2,634: | ||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
< |
<syntaxhighlight lang=rust>extern crate libc; |
||
//c function that returns the sum of two integers |
//c function that returns the sum of two integers |
||
Line 2,646: | Line 2,646: | ||
add_input(in1, in2) }; |
add_input(in1, in2) }; |
||
assert!( (output == (in1 + in2) ),"Error in sum calculation") ; |
assert!( (output == (in1 + in2) ),"Error in sum calculation") ; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
< |
<syntaxhighlight lang=Scala>object JNIDemo { |
||
try System.loadLibrary("JNIDemo") |
try System.loadLibrary("JNIDemo") |
||
Line 2,655: | Line 2,655: | ||
println(callStrdup("Hello World!")) |
println(callStrdup("Hello World!")) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
The way external functions are declared is different among Smalltalk dialects. However, there are not many situations where you'd need them (and especially not for simple things like strdup). |
The way external functions are declared is different among Smalltalk dialects. However, there are not many situations where you'd need them (and especially not for simple things like strdup). |
||
{{works with | Smalltalk/X}} |
{{works with | Smalltalk/X}} |
||
< |
<syntaxhighlight lang=Smalltalk>Object subclass:'CallDemo'! |
||
!CallDemo class methods! |
!CallDemo class methods! |
||
strdup:arg |
strdup:arg |
||
Line 2,666: | Line 2,666: | ||
! ! |
! ! |
||
Transcript showCR:( CallDemo strdup:'Hello' )</ |
Transcript showCR:( CallDemo strdup:'Hello' )</syntaxhighlight> |
||
=={{header|Stata}}== |
=={{header|Stata}}== |
||
Line 2,676: | Line 2,676: | ||
As an example let's build a '''[https://en.wikipedia.org/wiki/Hilbert_matrix Hilbert matrix]''' in C. |
As an example let's build a '''[https://en.wikipedia.org/wiki/Hilbert_matrix Hilbert matrix]''' in C. |
||
< |
<syntaxhighlight lang=c>#include <stdlib.h> |
||
#include "stplugin.h" |
#include "stplugin.h" |
||
Line 2,689: | Line 2,689: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
The DLL can be built from '''Visual Studio''', or in the console with <code>cl /LD hilbertmat.c stplugin.c</code>. With '''MinGW''', compile with <code>gcc -shared stplugin.c hilbertmatrix.c -o hilbertmat.plugin</code>. With '''Pelles C''', compile with <code>cc /Tx64-coff /Ze stplugin.c hilbertmat.c /DLL /OUT:hilbertmat.plugin</code>. The DLL must be renamed with the '''.plugin''' extension, and put in a directory visible in [https://www.stata.com/help.cgi?adopath adopath]. |
The DLL can be built from '''Visual Studio''', or in the console with <code>cl /LD hilbertmat.c stplugin.c</code>. With '''MinGW''', compile with <code>gcc -shared stplugin.c hilbertmatrix.c -o hilbertmat.plugin</code>. With '''Pelles C''', compile with <code>cc /Tx64-coff /Ze stplugin.c hilbertmat.c /DLL /OUT:hilbertmat.plugin</code>. The DLL must be renamed with the '''.plugin''' extension, and put in a directory visible in [https://www.stata.com/help.cgi?adopath adopath]. |
||
Line 2,695: | Line 2,695: | ||
Declare also an ADO file to call the plugin: |
Declare also an ADO file to call the plugin: |
||
< |
<syntaxhighlight lang=stata>program hilbert |
||
matrix define `1'=J(`2',`2',0) |
matrix define `1'=J(`2',`2',0) |
||
plugin call hilbertmat, `1' `2' |
plugin call hilbertmat, `1' `2' |
||
end |
end |
||
program hilbertmat, plugin</ |
program hilbertmat, plugin</syntaxhighlight> |
||
Then, you may call |
Then, you may call |
||
< |
<syntaxhighlight lang=stata>. hilbert mymat 4 |
||
. matrix list mymat |
. matrix list mymat |
||
Line 2,713: | Line 2,713: | ||
r2 .5 .33333333 |
r2 .5 .33333333 |
||
r3 .33333333 .25 .2 |
r3 .33333333 .25 .2 |
||
r4 .25 .2 .16666667 .14285714</ |
r4 .25 .2 .16666667 .14285714</syntaxhighlight> |
||
Notice the program as is has minimal protection against invalid arguments. Production code should be more careful. |
Notice the program as is has minimal protection against invalid arguments. Production code should be more careful. |
||
Line 2,722: | Line 2,722: | ||
As an example let's build a '''[https://en.wikipedia.org/wiki/Hilbert_matrix Hilbert matrix]''' in Java. |
As an example let's build a '''[https://en.wikipedia.org/wiki/Hilbert_matrix Hilbert matrix]''' in Java. |
||
< |
<syntaxhighlight lang=java>import com.stata.sfi.*; |
||
public class HilbertMatrix { |
public class HilbertMatrix { |
||
Line 2,737: | Line 2,737: | ||
return 0; |
return 0; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Compile with <code>javac -cp %STATA%\utilities\jar\sfi-api.jar HilbertMatrix.java</code>, assuming %STATA% is the path to the Stata install directory. |
Compile with <code>javac -cp %STATA%\utilities\jar\sfi-api.jar HilbertMatrix.java</code>, assuming %STATA% is the path to the Stata install directory. |
||
Line 2,743: | Line 2,743: | ||
In Stata, assuming HilbertMatrix.class resides in K:\java: |
In Stata, assuming HilbertMatrix.class resides in K:\java: |
||
< |
<syntaxhighlight lang=stata>. javacall HilbertMatrix run, classpath(K:\java) args(mymat 4) |
||
. matrix list mymat |
. matrix list mymat |
||
Line 2,752: | Line 2,752: | ||
r2 .5 .33333333 |
r2 .5 .33333333 |
||
r3 .33333333 .25 .2 |
r3 .33333333 .25 .2 |
||
r4 .25 .2 .16666667 .14285714</ |
r4 .25 .2 .16666667 .14285714</syntaxhighlight> |
||
Notice that Mata has the builtin function '''[https://www.stata.com/help.cgi?mf_Hilbert Hilbert]''' to do the same: |
Notice that Mata has the builtin function '''[https://www.stata.com/help.cgi?mf_Hilbert Hilbert]''' to do the same: |
||
< |
<syntaxhighlight lang=stata>. mata: Hilbert(4) |
||
[symmetric] |
[symmetric] |
||
1 2 3 4 |
1 2 3 4 |
||
Line 2,764: | Line 2,764: | ||
3 | .3333333333 .25 .2 | |
3 | .3333333333 .25 .2 | |
||
4 | .25 .2 .1666666667 .1428571429 | |
4 | .25 .2 .1666666667 .1428571429 | |
||
+---------------------------------------------------------+</ |
+---------------------------------------------------------+</syntaxhighlight> |
||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
Because Swift uses the Objective-C runtime it is trivial to call C/Objective-C functions directly in Swift. |
Because Swift uses the Objective-C runtime it is trivial to call C/Objective-C functions directly in Swift. |
||
< |
<syntaxhighlight lang=Swift>import Foundation |
||
let hello = "Hello, World!" |
let hello = "Hello, World!" |
||
let fromC = strdup(hello) |
let fromC = strdup(hello) |
||
let backToSwiftString = String.fromCString(fromC)</ |
let backToSwiftString = String.fromCString(fromC)</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{libheader|critcl}} |
{{libheader|critcl}} |
||
In this solution, we wrap up the <code>ilogb</code> function from C's math library with critcl so that it becomes one of Tcl's normal functions (assuming Tcl 8.5): |
In this solution, we wrap up the <code>ilogb</code> function from C's math library with critcl so that it becomes one of Tcl's normal functions (assuming Tcl 8.5): |
||
< |
<syntaxhighlight lang=tcl>package require critcl |
||
critcl::code { |
critcl::code { |
||
#include <math.h> |
#include <math.h> |
||
Line 2,784: | Line 2,784: | ||
return ilogb(value); |
return ilogb(value); |
||
} |
} |
||
package provide ilogb 1.0</ |
package provide ilogb 1.0</syntaxhighlight> |
||
Note that we do not show <code>strdup</code> here because Tcl manages the memory for strings in complex ways and does not guarantee to preserve string pointers from one call into the C API to the next (e.g., if it has to apply an encoding transformation behind the scenes). |
Note that we do not show <code>strdup</code> here because Tcl manages the memory for strings in complex ways and does not guarantee to preserve string pointers from one call into the C API to the next (e.g., if it has to apply an encoding transformation behind the scenes). |
||
<!-- TODO: a basic thunk, and show off using SWIG --> |
<!-- TODO: a basic thunk, and show off using SWIG --> |
||
Line 2,807: | Line 2,807: | ||
Although RC task solutions are usually written for execution by Wren CLI, the language's main purpose is for embedding and the embedding API is written in C. It is therefore a relative easy matter to call a C function from Wren after first embedding the latter in a suitable C program. |
Although RC task solutions are usually written for execution by Wren CLI, the language's main purpose is for embedding and the embedding API is written in C. It is therefore a relative easy matter to call a C function from Wren after first embedding the latter in a suitable C program. |
||
< |
<syntaxhighlight lang=ecmascript>/* call_foreign_language_function.wren */ |
||
class C { |
class C { |
||
Line 2,814: | Line 2,814: | ||
var s = "Hello World!" |
var s = "Hello World!" |
||
System.print(C.strdup(s))</ |
System.print(C.strdup(s))</syntaxhighlight> |
||
which we embed in the following C program and run it. |
which we embed in the following C program and run it. |
||
Note that it's safe to free the pointer returned by strdup after passing it to Wren because wrenSetSlotString copies the C string to a new String object managed by Wren’s garbage collector. |
Note that it's safe to free the pointer returned by strdup after passing it to Wren because wrenSetSlotString copies the C string to a new String object managed by Wren’s garbage collector. |
||
< |
<syntaxhighlight lang=C>#include <stdlib.h> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |
||
Line 2,901: | Line 2,901: | ||
free(script); |
free(script); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,911: | Line 2,911: | ||
===UASM 2.52=== |
===UASM 2.52=== |
||
Calling C functions in Assembly is trivial at best. It's not anymore complicated than using them in C itself. Strdup for example.. |
Calling C functions in Assembly is trivial at best. It's not anymore complicated than using them in C itself. Strdup for example.. |
||
< |
<syntaxhighlight lang=asm> |
||
option casemap:none |
option casemap:none |
||
Line 2,942: | Line 2,942: | ||
;main endp |
;main endp |
||
;end |
;end |
||
</syntaxhighlight> |
|||
</lang> |
|||
====Lua==== |
====Lua==== |
||
Using the liblua that comes with Lua 5.2(?). Assembling is the same as always, Link with a -llua using clang or gcc. |
Using the liblua that comes with Lua 5.2(?). Assembling is the same as always, Link with a -llua using clang or gcc. |
||
< |
<syntaxhighlight lang=asm> |
||
option casemap:none |
option casemap:none |
||
Line 3,192: | Line 3,192: | ||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
Addition.lua |
Addition.lua |
||
< |
<syntaxhighlight lang=lua> |
||
function addition(a, b) |
function addition(a, b) |
||
print('---> Lua calc: ' .. a .. ' + ' .. b .. ' = ' .. a+b) |
print('---> Lua calc: ' .. a .. ' + ' .. b .. ' = ' .. a+b) |
||
return a + b |
return a + b |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 3,214: | Line 3,214: | ||
{{trans|Wren}} |
{{trans|Wren}} |
||
So yeah. This inits Wrens VM in Assembly to call strdup in C. Now PIE(Position independent executable) compliant. |
So yeah. This inits Wrens VM in Assembly to call strdup in C. Now PIE(Position independent executable) compliant. |
||
< |
<syntaxhighlight lang=asm> |
||
;; libc stuff.. |
;; libc stuff.. |
||
extern printf |
extern printf |
||
Line 3,392: | Line 3,392: | ||
ret |
ret |
||
</syntaxhighlight> |
|||
</lang> |
|||
strdup.wren |
strdup.wren |
||
< |
<syntaxhighlight lang=wren> |
||
class C { |
class C { |
||
foreign static strdup(s) |
foreign static strdup(s) |
||
Line 3,400: | Line 3,400: | ||
var s = "Goodbye, World!" |
var s = "Goodbye, World!" |
||
System.print(C.strdup(s)) |
System.print(C.strdup(s)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
strdup.c |
strdup.c |
||
<syntaxhighlight lang=c> |
|||
<lang c> |
|||
void free( void* ptr ); |
void free( void* ptr ); |
||
char * strdup( const char *str1 ); |
char * strdup( const char *str1 ); |
||
Line 3,416: | Line 3,416: | ||
free(t); |
free(t); |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 3,424: | Line 3,424: | ||
=={{header|Zig}}== |
=={{header|Zig}}== |
||
< |
<syntaxhighlight lang=zig>const std = @import("std"); |
||
const c = @cImport({ |
const c = @cImport({ |
||
@cInclude("stdlib.h"); // `free` |
@cInclude("stdlib.h"); // `free` |
||
Line 3,436: | Line 3,436: | ||
try std.io.getStdOut().writer().print("{s}\n", .{copy}); |
try std.io.getStdOut().writer().print("{s}\n", .{copy}); |
||
c.free(copy); |
c.free(copy); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
Line 3,444: | Line 3,444: | ||
flf.c: |
flf.c: |
||
< |
<syntaxhighlight lang=c>//-*-c-*- |
||
// flf.c, Call a foreign-language function |
// flf.c, Call a foreign-language function |
||
Line 3,479: | Line 3,479: | ||
} |
} |
||
return methodCreate(Void,0,zkl_strlen,vm); |
return methodCreate(Void,0,zkl_strlen,vm); |
||
}</ |
}</syntaxhighlight> |
||
In use on Linux: |
In use on Linux: |
||
{{out}} |
{{out}} |