Call a function in a shared library: Difference between revisions

m
→‎{{header|Wren}}: Capitalize Wren & C file names.
m (→‎{{header|REXX}}: aligned a couple of comments.)
m (→‎{{header|Wren}}: Capitalize Wren & C file names.)
 
(31 intermediate revisions by 21 users not shown)
Line 1:
[[Category:Functions and subroutines]]
{{task|Programming environment operations}}
Show how to call a function in a shared library (without dynamically linking to it at compile-time). In particular, show how to call the shared library function if the library is available, otherwise use an internal equivalent function.
 
This is a special case of [[Call foreign language function|calling a foreign language function]] where the focus is close to the [https://en.wikipedia.org/wiki/Application_binary_interface ABI] level and not at the normal API level.
 
 
Line 8 ⟶ 9:
* [[OpenGL]] -- OpenGL is usually maintained as a shared library.
<br><br>
 
=={{header|Ada}}==
===Windows===
The following solution calls ''MessageBox'' from [[Windows]]' dynamic library ''user32.dll''. It does not use Win32 bindings, which would be meaningless, because ''MessageBox'' is already there. Instead of that it links statically to ''kernel32.dll'', which required to load anything under [[Windows]]. From there it uses ''LoadLibrary'' to load ''user32.dll'' and then ''GetProcAddress'' to get the ''MessageBox'' entry point there. Note how [[Windows]] mangles names of functions in the import libraries. So "LoadLibrary" becomes "_LoadLibraryA@4", which is its real name. "A" means ASCII. Once address of ''MessageBox'' is obtained it is converted to a pointer to a function that has an interface corresponding to it. Note [[Windows]]' call convention, which is '''stdcall'''.
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Interfaces; use Interfaces;
with Interfaces.C; use Interfaces.C;
Line 24:
-- There are ready to use Win32 bindings. We don't want to use them here.
--
type HANDLE is new Unsigned_32; -- on x64 system, replace by Unsigned_64 to make it work
function LoadLibrary (lpFileName : char_array) return HANDLE;
pragma Import (stdcall, LoadLibrary, "LoadLibrary", "_LoadLibraryA"); -- Ada95 does not have the @n suffix.
Line 56:
Put_Line ("Unable to load the library " & HANDLE'Image (Library));
end if;
end Shared_Library_Call;</langsyntaxhighlight>
 
===Linux===
Here we are using the ''dl'' library statically (-ldl switch upon linking) and ''Xlib'' dynamically (''libX11.so''). The function ''dlopen'' loads a library. The function ''dlsym'' looks up for an entry point there. From ''libX11.so'', first ''XOpenDisplay'' is called to open an X11 display, which name is in the DISPLAY environment variable. Then XDisplayWidth of the display is obtained an printed into the standard output.
<langsyntaxhighlight Adalang="ada">with Ada.Environment_Variables; use Ada.Environment_Variables;
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces; use Interfaces;
Line 108:
Put_Line ("Unable to load the library");
end if;
end Shared_Library_Call;</langsyntaxhighlight>
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">getCurlVersion: function [][
try? [
call.external:'curl "curl_version" .expect: :string []
]
else [
"library not found"
]
]
 
print ["curl version:" getCurlVersion]</syntaxhighlight>
 
{{out}}
 
<pre>curl version: libcurl/7.64.1 SecureTransport (LibreSSL/2.8.3) zlib/1.2.11 nghttp2/1.41.0 </pre>
=={{header|AutoHotkey}}==
{{works with|http://www.autohotkey.net/~tinku99/ahkdll/ AutoHotkey.dll}}<br>
dllhost.ahk
<langsyntaxhighlight AutoHotkeylang="autohotkey">ahkdll := DllCall("LoadLibrary", "str", "AutoHotkey.dll")
clientHandle := DllCall("AutoHotkey\ahkdll", "str", "dllclient.ahk", "str"
, "", "str", "parameter1 parameter2", "Cdecl Int")</langsyntaxhighlight>
dllclient.ahk
<syntaxhighlight lang AutoHotkey="autohotkey">Msgbox, hello from client</langsyntaxhighlight>
 
=={{header|BaCon}}==
 
=={{header|BASIC}}==
<lang qbasic>' Call a dynamic library function
==={{header|BaCon}}===
<syntaxhighlight lang="qbasic">' Call a dynamic library function
PROTO j0
bessel0 = j0(1.0)
PRINT bessel0
</syntaxhighlight>
</lang>
 
{{out}}
Line 136 ⟶ 151:
0.765198</pre>
 
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
The following shared libraries are automatically available: ADVAPI32.DLL, COMCTL32.DLL, COMDLG32.DLL, GDI32.DLL, KERNEL32.DLL, SHELL32.DLL, USER32.DLL and WINMM.DLL.
<langsyntaxhighlight lang="bbcbasic"> SYS "MessageBox", @hwnd%, "This is a test message", 0, 0
</syntaxhighlight>
</lang>
 
=={{header|C}}==
Line 147 ⟶ 162:
'''Tested with''' gcc on a GNU/Linux system (on GNU/Linux <code>dl*</code> functions are available linking to <tt>libdl</tt>, i.e. with <tt>-ldl</tt> option)
 
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
Line 182 ⟶ 197:
if (imglib != NULL ) dlclose(imglib);
return EXIT_SUCCESS;
}</langsyntaxhighlight>
 
The fake <tt>fakeimglib.so</tt> code is
 
<langsyntaxhighlight lang="c">#include <stdio.h>
/* gcc -shared -nostartfiles fakeimglib.c -o fakeimglib.so */
int openimage(const char *s)
Line 193 ⟶ 208:
fprintf(stderr, "opening %s\n", s);
return handle++;
}</langsyntaxhighlight>
 
When the library <tt>fakeimglib.so</tt> exists in the current directory (this choice is senseful only for testing purposes), the output is:
Line 204 ⟶ 219:
<pre>internal openimage opens fake.img...
opened with handle 0</pre>
 
=={{header|C sharp|C#}}==
In Windows.
<langsyntaxhighlight lang="csharp">using System.Runtime.InteropServices;
 
class Program {
Line 216 ⟶ 230:
int r = fakefunction(10);
}
}</langsyntaxhighlight>
 
=={{header|COBOL}}==
Tested with GnuCOBOL, GNU/Linux.
 
<langsyntaxhighlight lang="cobol"> identification division.
program-id. callsym.
 
Line 257 ⟶ 270:
 
goback.
end program callsym.</langsyntaxhighlight>
 
{{out}}
<pre>prompt$ cobc -xj callsym.cob
Success</pre>
 
=={{header|Common Lisp}}==
 
{{libheader|CFFI}}
 
<langsyntaxhighlight lang="lisp">CL-USER> (cffi:load-foreign-library "libX11.so")
#<CFFI::FOREIGN-LIBRARY {1004F4ECC1}>
CL-USER> (cffi:foreign-funcall "XOpenDisplay"
Line 273 ⟶ 285:
#-sbcl ":0.0"
:pointer)
#.(SB-SYS:INT-SAP #X00650FD0)</langsyntaxhighlight>
=={{header|Crystal}}==
 
<syntaxhighlight lang="ruby">libm = LibC.dlopen("libm.so.6", LibC::RTLD_LAZY)
sqrtptr = LibC.dlsym(libm, "sqrt") unless libm.null?
 
if sqrtptr
sqrtproc = Proc(Float64, Float64).new sqrtptr, Pointer(Void).null
at_exit { LibC.dlclose(libm) }
else
sqrtproc = ->Math.sqrt(Float64)
end
 
puts "the sqrt of 4 is #{sqrtproc.call(4.0)}"</syntaxhighlight>
=={{header|D}}==
<langsyntaxhighlight lang="d">pragma(lib, "user32.lib");
 
import std.stdio, std.c.windows.windows;
Line 284 ⟶ 308:
void main() {
writeln(GetDoubleClickTime());
}</langsyntaxhighlight>
 
<pre>500</pre>
 
=={{header|Dart}}==
 
add.c
<syntaxhighlight lang="c">
<lang c>
int add(int num1, int num2) {
return num1 + num2;
}
</syntaxhighlight>
</lang>
 
Dart code
<langsyntaxhighlight lang="javascript">import 'dart:ffi'
show DynamicLibrary, NativeFunction, Int32;
 
Line 310 ⟶ 333:
print( add( 1, 2 ) );
}
</syntaxhighlight>
</lang>
 
=={{header|Delphi}}==
 
Line 317 ⟶ 339:
Loads library on startup.
 
<langsyntaxhighlight Delphilang="delphi">procedure DoSomething; external 'MYLIB.DLL';</langsyntaxhighlight>
 
 
Line 323 ⟶ 345:
Loads library on first call to DoSomething.
 
<langsyntaxhighlight Delphilang="delphi">procedure DoSomething; external 'MYLIB.DLL' delayed;</langsyntaxhighlight>
 
 
Line 329 ⟶ 351:
Loads and unloads library on demand.
 
<syntaxhighlight lang="delphi">var
<lang Delphi>var
lLibraryHandle: THandle;
lDoSomething: procedure; stdcall;
Line 340 ⟶ 362:
FreeLibrary(lLibraryHandle);
end;
end;</langsyntaxhighlight>
 
=={{header|Ecstasy}}==
Ecstasy was designed around software containers and a strong security model. As such, Ecstasy does not have an FFI, and Ecstasy code cannot direcly access operating system or other foreign functions. More specifically, code running within an Ecstasy container cannot call foreign functions; any such required capabilities must be implemented outside of Ecstasy (for example, in C) and then <i>injected</i> into an Ecstasy container.
 
=={{header|Forth}}==
===GNU Forth 0.7.9 on Linux===
Call tgamma() from limbm.so
<syntaxhighlight lang="forth">
c-library math
 
s" m" add-lib
\c #include <math.h>
c-function gamma tgamma r -- r
 
end-c-library
</syntaxhighlight>
{{Out}}
<pre>
require ./foreign.fs ok
1.01e2 gamma fs. 9.33262154439442E157 ok
</pre>
=={{header|Fortran}}==
===GNU Fortran on Linux===
Line 349 ⟶ 391:
 
A simple "C" function add_n in add_n.c
<syntaxhighlight lang="c">
<lang c>
double add_n(double* a, double* b)
{
return *a + *b;
}
</langsyntaxhighlight>
 
compile it
Line 363 ⟶ 405:
 
File add_nf.f90
<langsyntaxhighlight lang="fortran">
function add_nf(a,b) bind(c, name='add_nf')
use, intrinsic :: iso_c_binding
Line 372 ⟶ 414:
add_nf = a + b
end function add_nf
</langsyntaxhighlight>
Compile it
 
Line 385 ⟶ 427:
 
File shared_lib_new_test.f90
<langsyntaxhighlight lang="fortran">
!-----------------------------------------------------------------------
!module dll_module
Line 661 ⟶ 703:
end program test_load_dll
 
</syntaxhighlight>
</lang>
Compile test program
 
Line 683 ⟶ 725:
===Intel Fortran on Windows===
First, the DLL. Compile with '''ifort /dll dllfun.f90'''. The function is compiled with the STDCALL calling convention: it's not necessary here but it shows how to do it.
<langsyntaxhighlight lang="fortran">function ffun(x, y)
implicit none
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE :: FFUN
double precision :: x, y, ffun
ffun = x + y * y
end function</langsyntaxhighlight>
 
Now, the main program. It will wait for two numbers and compute the result with the DLL function. Compile with '''ifort dynload.f90'''. Three functions of the Kernel32 library are necessary, see '''[https://msdn.microsoft.com/en-us/library/ms684175.aspx LoadLibrary]''', '''[https://msdn.microsoft.com/en-us/library/ms683212.aspx GetProcAddress]''' and '''[https://msdn.microsoft.com/en-us/library/ms683152.aspx FreeLibrary]''' in the MSDN. The kernel32 module is provided with the Intel Fortran compiler. The DLL has to be in a directory in the PATH environment variable.
 
<langsyntaxhighlight lang="fortran">program dynload
use kernel32
use iso_c_binding
Line 721 ⟶ 763:
if (FreeLibrary(h) == 0) error stop "Error: FreeLibrary"
end program</langsyntaxhighlight>
 
=== GNU Fortran on Windows ===
Line 735 ⟶ 777:
 
First the DLL:
<langsyntaxhighlight lang="fortran">function ffun(x, y)
implicit none
!GCC$ ATTRIBUTES DLLEXPORT, STDCALL :: FFUN
double precision :: x, y, ffun
ffun = x + y * y
end function</langsyntaxhighlight>
 
Main program:
<langsyntaxhighlight lang="fortran">program dynload
use kernel32
use iso_c_binding
Line 772 ⟶ 814:
if (FreeLibrary(h) == 0) error stop "Error: FreeLibrary"
end program</langsyntaxhighlight>
 
Interface module:
<langsyntaxhighlight lang="fortran">module kernel32
use iso_c_binding
implicit none
Line 809 ⟶ 851:
end function
end interface
end module</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
' Attempt to call Beep function in Win32 API
Line 834 ⟶ 875:
Print
Print "Press any key to quit"
Sleep</langsyntaxhighlight>
 
 
=={{header|FutureBasic}}==
Use GameplayKit framework to quickly generate random integers.
<syntaxhighlight lang="futurebasic">
include "tlbx GameplayKit.incl"
 
UInt64 randomInteger
NSUInteger i
 
for i = 1 to 20
randomInteger = fn GKLinearCongruentialRandomSourceSeed( fn GKLinearCongruentialRandomSourceInit )
print randomInteger
next
 
HandleEvents
</syntaxhighlight>
 
 
=={{header|Go}}==
Line 843 ⟶ 902:
 
This is the C code to produce fakeimglib.so:
<langsyntaxhighlight lang="c">#include <stdio.h>
/* gcc -shared -fPIC -nostartfiles fakeimglib.c -o fakeimglib.so */
int openimage(const char *s)
Line 850 ⟶ 909:
fprintf(stderr, "opening %s\n", s);
return handle++;
}</langsyntaxhighlight>
And this is the Go code to dynamically load the .so file and call the 'openimage' function - or if the .so file (or the function itself) is not available, to call the internal version of the function:
<langsyntaxhighlight lang="go">package main
 
/*
Line 903 ⟶ 962:
}
fmt.Printf("opened with handle %d\n", imghandle)
}</langsyntaxhighlight>
 
{{output}}
Line 909 ⟶ 968:
Same as C entry.
</pre>
 
=={{header|Haskell}}==
 
Line 915 ⟶ 973:
{{libheader|unix}}
 
<langsyntaxhighlight lang="haskell">#!/usr/bin/env stack
-- stack --resolver lts-6.33 --install-ghc runghc --package unix
 
Line 955 ⟶ 1,013:
Right f -> ("Using BUF_reverse from OpenSSL", f)
putStrLn msg
putStrLn $ rev "a man a plan a canal panama"</langsyntaxhighlight>
 
=={{header|J}}==
Most of this was borrowed from [[Call a foreign-language function#J]]
<langsyntaxhighlight Jlang="j">require 'dll'
strdup=: 'msvcrt.dll _strdup >x *' cd <
free=: 'msvcrt.dll free n x' cd <
Line 970 ⟶ 1,027:
y
end.
)</langsyntaxhighlight>
 
You get a domain error when the required library is not present at run time. A try/catch will let you handle this (as would the <code>::</code> adverse operator).
 
Example use:
<langsyntaxhighlight Jlang="j"> DupStr 'hello'
hello
getstr@strdup ::] 'hello'
hello</langsyntaxhighlight>
 
=={{header|Java}}==
For methods with the <tt>native</tt> keyword, the library must be written to the [[wp:Java Native Interface|Java Native Interface]]; this is not a general [[FFI]]. If the library is missing, <code>System.loadLibrary()</code> throws <code>UnsatisfiedLinkError</code>. We can continue if we catch this error and then don't call the library's native methods.
Line 985 ⟶ 1,041:
If you have Unix [[make]], then edit the ''Makefile'', run <code>make</code>, run <code>java -Djava.library.path=. RSort</code>. If you don't set java.library.path, or don't build the library, then the Java code falls back from using C to using Java. For more info about building a JNI library, see [[Call a foreign-language function#Java]].
 
<langsyntaxhighlight lang="java">/* TrySort.java */
 
import java.util.Collections;
Line 1,055 ⟶ 1,111:
System.out.println("ok");
}
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="c">/* TrySort.c */
 
#include <stdlib.h>
Line 1,090 ⟶ 1,146:
qsort(elem, length, sizeof(jint), reverse_abs_cmp);
(*jenv)->ReleasePrimitiveArrayCritical(jenv, ary, elem, 0);
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="make"># Makefile
 
# Edit the next lines to match your JDK.
Line 1,118 ⟶ 1,174:
clean:
rm -f TrySort.class TrySort?IntList.class \
TrySort?ReverseAbsCmp.class TrySort.h $(LIB)</langsyntaxhighlight>
 
===JNA===
{{libheader|JNA}}
<langsyntaxhighlight lang="java">import com.sun.jna.Library;
import com.sun.jna.Native;
 
Line 1,136 ⟶ 1,192:
lib.sharedLibraryFunction();
}
}</langsyntaxhighlight>
 
=={{header|Jsish}}==
Jsish includes a '''load('library.so');''' function, which calls a specially crafted management function in the library,
Line 1,144 ⟶ 1,199:
Normally, this function would register commands to the shell, but this is just a DISPLAY statement on load, and then again on unload as jsish runs down. Note the name used, "Jsi_Initbyjsi", from "byjsi.so".
 
<langsyntaxhighlight lang="javascript">#!/usr/local/bin/jsish
load('byjsi.so');</langsyntaxhighlight>
 
For example, a COBOL library generated from
 
<langsyntaxhighlight COBOLlang="cobol"> identification division.
program-id. sample as "Jsi_Initbyjsi".
 
Line 1,174 ⟶ 1,229:
display "Called again with: " jsi-interp ", " rel upon syserr
goback.
end program sample.</langsyntaxhighlight>
 
{{out}}
Line 1,182 ⟶ 1,237:
Called again with: 0x00000000013a9260, +0000000002
prompt$</pre>
 
=={{header|Julia}}==
Julia has the `ccall` function which follows the form: ccall((symbol, library), RetType, (ArgType1, ...), ArgVar1, ...)
<langsyntaxhighlight lang="julia">
#this example works on Windows
ccall( (:GetDoubleClickTime, "User32"), stdcall,
Uint, (), )
 
ccall( (:clock, "libc"), Int32, ())</langsyntaxhighlight>
For more information, see here [http://docs.julialang.org/en/latest/manual/calling-c-and-fortran-code.html]
 
=={{header|Kotlin}}==
{{trans|C}}
Line 1,198 ⟶ 1,251:
 
This is the C code to produce fakeimglib.so:
<langsyntaxhighlight Clang="c">#include <stdio.h>
/* gcc -shared -fPIC -nostartfiles fakeimglib.c -o fakeimglib.so */
int openimage(const char *s)
Line 1,205 ⟶ 1,258:
fprintf(stderr, "opening %s\n", s);
return handle++;
}</langsyntaxhighlight>
And this is the Kotlin code to dynamically load the .so file and call the 'openimage' function - or if the .so file (or the function itself) is not available, to call the internal version of the function:
<langsyntaxhighlight lang="scala">// Kotlin Native version 0.5
 
import kotlinx.cinterop.*
Line 1,240 ⟶ 1,293:
}
println("opened with handle $imgHandle")
}</langsyntaxhighlight>
 
{{out}}
Line 1,246 ⟶ 1,299:
Same as C entry
</pre>
 
=={{header|Lingo}}==
<langsyntaxhighlight lang="lingo">-- calculate CRC-32 checksum
str = "The quick brown fox jumps over the lazy dog"
 
Line 1,265 ⟶ 1,317:
crc = crcObj.crc32(str)
 
end if</langsyntaxhighlight>
=={{header|Lua}}==
 
There is no built-in mechanism, but several external library options exist. Here, the alien library is used to display a message box via the Win32 API.
<syntaxhighlight lang="lua">alien = require("alien")
msgbox = alien.User32.MessageBoxA
msgbox:types({ ret='long', abi='stdcall', 'long', 'string', 'string', 'long' })
retval = msgbox(0, 'Please press Yes, No or Cancel', 'The Title', 3)
print(retval) --> 6, 7 or 2</syntaxhighlight>
=={{header|Maple}}==
<langsyntaxhighlight Maplelang="maple">> cfloor := define_external( floor, s::float[8], RETURN::float[8], LIB = "libm.so" ):
> cfloor( 2.3 );
2.</langsyntaxhighlight>
 
=={{header|MathematicaLambdatalk}}==
 
Lambdatalk works in a wiki, lambdatank, hosted by any web browser coming with Javascript. Javascript has no native tools dealing with big numbers. Jonas Raoni Soares Silva has built a smart JS library, http://jsfromhell.com/classes/bignumber, which can be loaded in a wiki page, so called "lib_BN". Obviously interfaces must be built, for instance the BN.* operator multiplying two big numbers:.
 
<syntaxhighlight lang="scheme">
{script
LAMBDATALK.DICT['BN.*'] = function(){
var args = arguments[0].split(' '),
a = new BigNumber( args[0], BN_DEC ),
b = new BigNumber( args[1], BN_DEC );
return a.multiply( b )
};
</syntaxhighlight>
 
The lib_BN library can be loaded in any other wiki page via a {require lib_BN} expression and the BN.* primitive can be used this way:
 
<syntaxhighlight lang="scheme">
{BN.* 123456789123456789123456789 123456789123456789123456789}
-> 15241578780673678546105778281054720515622620750190521
 
to be compared with the "standard" lambdatalk builtin * operator
 
{* 123456789123456789123456789 123456789123456789123456789}
-> 1.524157878067368e+52
</syntaxhighlight>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
This works on windows and on linux/mac too (through Mono)
<langsyntaxhighlight Mathematicalang="mathematica">Needs["NETLink`"];
externalFloor = DefineDLLFunction["floor", "msvcrt.dll", "double", { "double" }];
externalFloor[4.2]
-> 4.</langsyntaxhighlight>
 
=={{header|Nim}}==
===Interacting with C code===
<langsyntaxhighlight lang="nim">proc openimage(s: cstring): cint {.importc, dynlib: "./fakeimglib.so".}
 
echo openimage("foo")
echo openimage("bar")
echo openimage("baz")</langsyntaxhighlight>
The fake <code>fakeimglib.so</code> code is
<langsyntaxhighlight lang="c">#include <stdio.h>
/* gcc -shared -nostartfiles fakeimglib.c -o fakeimglib.so */
int openimage(const char *s)
Line 1,294 ⟶ 1,377:
fprintf(stderr, "opening %s\n", s);
return handle++;
}</langsyntaxhighlight>
Output:
<pre>opening foo
Line 1,304 ⟶ 1,387:
 
===Interacting with Nim code===
<langsyntaxhighlight lang="nim">proc openimage(s: string): int {.importc, dynlib: "./libfakeimg.so".}
 
echo openimage("foo")
echo openimage("bar")
echo openimage("baz")</langsyntaxhighlight>
The fake <code>libfakeimg.so</code> code is
<langsyntaxhighlight lang="nim"># nim c --app:lib fakeimg.nim
var handle = 100
 
Line 1,316 ⟶ 1,399:
stderr.writeln "opening ", s
result = handle
inc(handle)</langsyntaxhighlight>
Output:
<pre>opening foo
Line 1,324 ⟶ 1,407:
opening baz
102</pre>
 
=={{header|OCaml}}==
As far as I know there is no solution in OCaml standard library to load a function from a C library dynamically. So I have quickly implemented [[Call a function in a shared library/OCaml|a module named Dlffi that you can find in this sub-page]]. It is basically a wrapper around the GNU/Linux dl* functions and the libffi.
Line 1,331 ⟶ 1,413:
 
Here is an example of use of this [[Call a function in a shared library/OCaml|Dlffi module]]:
<langsyntaxhighlight lang="ocaml">open Dlffi
 
let get_int = function Int v -> v | _ -> failwith "get_int"
Line 1,361 ⟶ 1,443:
Printf.printf "# Screen dimensions are: %d x %d pixels\n" width height;
dlclose xlib;
;;</langsyntaxhighlight>
 
=={{header|Ol}}==
 
Note: "strdup" is existent shared function, "strduX" is not existent.
Simplest case. Will produce memory leak, because no C "free" function called for dupped string. Useful when no "free" function call required.
<lang scheme>
<syntaxhighlight lang="scheme">
(import (otus ffi))
 
(define self (load-dynamic-library #f))
(define strdup (or
(self type-string "strdup" type-string))
(lambda (str)
(list->string (string->list str)))))
 
(print (strdup "Hello World!"))
(define strduX (or
</syntaxhighlight>
(self type-string "strduX" type-string)
 
(lambda (str)
A bit complex case. No memory leaks, because "free" function called for dupped string.
(list->string (string->list str)))))
<syntaxhighlight lang="scheme">
(import (otus ffi))
 
(define self (load-dynamic-library #f))
(define strdup
(let ((strdup (self type-vptr "strdup" type-string))
(free (self fft-void "free" type-vptr)))
(lambda (str)
(let*((dupped (strdup str))
(result (vptr->string dupped)))
(free dupped)
result))))
 
(print (strdup "Hello World!"))
</syntaxhighlight>
(print (strduX "Hello World!"))
 
</lang>
{{Out}}
<pre>
Hello World!
Hello World!
</pre>
 
=={{header|OxygenBasic}}==
<langsyntaxhighlight lang="oxygenbasic">
'Loading a shared library at run time and calling a function.
 
Line 1,403 ⟶ 1,493:
 
FreeLibrary user32
</syntaxhighlight>
</lang>
 
=={{header|PARI/GP}}==
<langsyntaxhighlight lang="parigp">install("function_name","G","gp_name","./test.gp.so");</langsyntaxhighlight>
where "G" is the parser code; see section 5.7.3 in the [http://pari.math.u-bordeaux.fr/pub/pari/manuals/2.4.4/libpari.pdf User's Guide to the PARI library] for more information.
 
=={{header|Pascal}}==
See [[Call_a_function_in_a_shared_library#Delphi | Delphi]]
 
=={{header|Perl}}==
Examples for simple <code>C</code> library calls, but each module is capable of much more (and can work with other languages). Refer to their documentation for details.
===Inline===
This modules auto-builds a wrapper to the library on the first call, and subsequently uses that interface with no delay.
<langsyntaxhighlight lang="perl">use Inline
C => "DATA",
ENABLE => "AUTOWRAP",
Line 1,425 ⟶ 1,512:
__DATA__
__C__
double atan(double x);</langsyntaxhighlight>
{{out}}
<pre>3.14159265358979</pre>
===FFI===
This module is smart about finding libraries, here getting <code>atan</code> (from 'lm') and <code>puts</code> (from 'libc').
<langsyntaxhighlight lang="perl">use FFI::Platypus;
my $ffi = FFI::Platypus->new;
$ffi->lib(undef);
Line 1,436 ⟶ 1,523:
$ffi->attach(atan => ['double'] => 'double');
 
puts(4*atan(1));</langsyntaxhighlight>
{{out}}
<pre>3.14159265358979</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(notonline)-->
<lang Phix>string {libname,funcname} = iff(platform()=WINDOWS?{"user32","CharLowerA"}:{"libc","tolower"})
<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>
atom lib = open_dll(libname)
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">libname</span><span style="color: #0000FF;">,</span><span style="color: #000000;">funcname</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">WINDOWS</span><span style="color: #0000FF;">?{</span><span style="color: #008000;">"user32"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"CharLowerA"</span><span style="color: #0000FF;">}:{</span><span style="color: #008000;">"libc"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tolower"</span><span style="color: #0000FF;">})</span>
integer func = define_c_func(lib,funcname,{C_INT},C_INT)
<span style="color: #004080;">atom</span> <span style="color: #000000;">lib</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_dll</span><span style="color: #0000FF;">(</span><span style="color: #000000;">libname</span><span style="color: #0000FF;">)</span>
if func=-1 then
<span style="color: #004080;">integer</span> <span style="color: #000000;">func</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">funcname</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">C_INT</span><span style="color: #0000FF;">},</span><span style="color: #000000;">C_INT</span><span style="color: #0000FF;">)</span>
?{{lower('A')}}
<span style="color: #008080;">if</span> <span style="color: #000000;">func</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
else
<span style="color: #0000FF;">?{{</span><span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">)}}</span> <span style="color: #000080;font-style:italic;">-- (you don't //have// to crash!)</span>
?c_func(func,{'A'}) -- ('A'==65)
<span style="color: #008080;">else</span>
end if</lang>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">func</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">})</span> <span style="color: #000080;font-style:italic;">-- ('A'==65)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
97 -- (or {{97}} if func not found)
</pre>
 
=={{header|PicoLisp}}==
This differs between the 32-bit and 64-bit versions. While the 64-bit version
Line 1,460 ⟶ 1,548:
===32-bit version===
For the 32-bit version, we need some glue code:
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/gcc.l")
 
(gcc "x11" '("-lX11") 'xOpenDisplay 'xCloseDisplay)
Line 1,485 ⟶ 1,573:
-> 158094320
: (xCloseDisplay Display)
-> 0</langsyntaxhighlight>
===64-bit version===
In the 64-bit version, we can call the library directly:
<langsyntaxhighlight PicoLisplang="picolisp">: (setq Display (native "/usr/lib/libX11.so.6" "XOpenDisplay" 'N ":0.0"))
-> 6502688
: (native "/usr/lib/libX11.so.6" "XCloseDisplay" 'I Display)
-> 0</langsyntaxhighlight>
 
=={{header|PowerBASIC}}==
{{Works with|PowerBASIC for Windows}}
In this example, if the library can't be found (user32), or the desired function in the library (MessageBoxA), the equivalent built-in function (MSGBOX) is at the "epicFail" label... but really, if you can't find user32.dll, you've got bigger things to worry about.
<langsyntaxhighlight lang="powerbasic">#INCLUDE "Win32API.inc"
 
FUNCTION PBMAIN () AS LONG
Line 1,532 ⟶ 1,619:
IF ISFALSE(tmp&) THEN MSGBOX "Error freeing library... [shrug]"
END IF
END FUNCTION</langsyntaxhighlight>
 
=={{header|PureBasic}}==
Older PureBasic versions normally relied on CallFunction() and CallFunctionFast()
<langsyntaxhighlight Purebasiclang="purebasic">if OpenLibrary(0, "USER32.DLL")
*MessageBox = GetFunction(0, "MessageBoxA")
CallFunctionFast(*MessageBox, 0, "Body", "Title", 0)
CloseLibrary(0)
endif</langsyntaxhighlight>
Since versions 4 the recommended way is via the usage of Prototypes even if the old system still is supported.
<langsyntaxhighlight PureBasiclang="purebasic">Prototype.l ProtoMessageBoxW(Window.l, Body.p-unicode, Title.p-unicode, Flags.l = 0)
 
If OpenLibrary(0, "User32.dll")
Line 1,548 ⟶ 1,634:
MsgBox(0, "Hello", "World")
CloseLibrary(0)
EndIf</langsyntaxhighlight>
 
=={{header|Python}}==
=== ctypes ===
Example that call User32.dll::GetDoubleClickTime() in windows.
<langsyntaxhighlight lang="python">import ctypes
user32_dll = ctypes.cdll.LoadLibrary('User32.dll')
print user32_dll.GetDoubleClickTime()</langsyntaxhighlight>
Or, to call printf out of the C standard library:
<langsyntaxhighlight lang="python">>>> import ctypes
>>> # libc = ctypes.cdll.msvcrt # Windows
>>> # libc = ctypes.CDLL('libc.dylib') # Mac
Line 1,564 ⟶ 1,649:
>>> libc.printf(b'hi there, %s\n', b'world')
hi there, world.
17</langsyntaxhighlight>
 
=== CFFI ===
[https://cffi.readthedocs.io/ CFFI] isn't built into the stdlib, but, on the other hand, it works with other Python implementations like PyPy. It also has a variety of advantages and disadvantages over ctypes, even for simple cases like this:
<langsyntaxhighlight lang="python">
>>> from cffi import FFI
>>> ffi = FFI()
Line 1,578 ⟶ 1,663:
>>> C.printf(b"hi there, %s.\n", arg) # call printf
hi there, world.
17</langsyntaxhighlight>
=={{header|QB64}}==
<syntaxhighlight lang="vb">
Declare Dynamic Library "Kernel32"
Sub SetLastError (ByVal dwErr As Long)
Function GetLastError& ()
End Declare
 
SetLastError 20
Print GetLastError</syntaxhighlight>
=={{header|R}}==
This is possible in R in only a few limited ways. If the library function one wishes to call is a (C-level) R function (of type SEXP), then one may call
<langsyntaxhighlight lang="rsplus">dyn.load("my/special/R/lib.so")
.Call("my_lib_fun", arg1, arg2)</langsyntaxhighlight>
It is also possible to use <code>.C()</code> and <code>.Fortran()</code> to call voids and subroutines respectively; here the return value(s) should be in the argument list (rather than merely modifying state). An example of this might look like
<langsyntaxhighlight lang="rsplus">.C("my_lib_fun", arg1, arg2, ret)</langsyntaxhighlight>
The return of the <code>.C()</code> function is an R list.
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
(require ffi/unsafe)
(define libm (ffi-lib "libm")) ; get a handle for the C math library
; look up sqrt in the math library. if we can't find it, return the builtin sqrt
(define extern-sqrt (get-ffi-obj 'sqrt libm (_fun _double -> _double)
(lambda () sqrt)))</langsyntaxhighlight>
 
Output: <pre>> (extern-sqrt 42.0)
6.48074069840786</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.11}}
<syntaxhighlight lang="raku" perl6line>use NativeCall;
 
sub XOpenDisplay(Str $s --> int64) is native('X11') {*}
Line 1,614 ⟶ 1,705:
say "No X11 library!";
say "Use this window instead --> ⬜";
}</langsyntaxhighlight>
{{out}}
<pre>ID = 94722089782960</pre>
 
=={{header|REXX}}==
{{works with|Regina REXX}}
Line 1,626 ⟶ 1,716:
 
The dropping of functions isn't really necessary for most REXX programs.
<langsyntaxhighlight lang="rexx">/*REXX program calls a function (sysTextScreenSize) in a shared library (regUtil). */
 
/*Note: the REGUTIL.DLL (REGina UTILity Dynamic Link Library */
/* should be in the PATH or the current directory. */
 
rca= rxFuncAdd('sysLoadFuncs', "regUtil", 'sysLoadFuncs') /*add a function library. */
Line 1,639 ⟶ 1,732:
exit rcl /*exit this program with RC. */
end
 
/* [↓] call a function. */
$= sysTextScreenSize() /*$ has 2 words: rows cols */
Line 1,651 ⟶ 1,743:
exit rcd /*exit this program with RC. */
end
exit 0 /*stick a fork in it, we're all done. */</langsyntaxhighlight>
{{out|output|text=&nbsp; (which happens to reflect the program's author's particular screen size for the "DOS" window):}}
<pre>
rows= 62
cols= 96
</pre>
=={{header|RPL}}==
There is no library concept in RPL. However, in 1990, Jan Christiaan van Winkel proposed to the RPL community a way to get something close.
Assuming the programs frequently needed are stored in a specific directory named <code>MyLib</code> located at root directory, the following program, also located at the root directory, can be invoked by any program to access one of the library features.
{{works with|Halcyon Calc|4.2.7}}
{| class="wikitable"
! RPL code
! Comment
|-
|
PATH ➜ owd
≪ HOME MyLib RCL
1 owd SIZE '''FOR''' i
owd i GET EVAL '''NEXT'''
≫ EVAL
≫ ''''CALL'''' STO
|
'''CALL''' ''( 'Program_name' -- depending on call )''
save the old directory
push the library routine on the stack
now go back to the old directory
step by step
run the library routine
|}
{{in}}
<pre>
97 'PRIM?' CALL
</pre>
{{out}}
<pre>
1: 1
</pre>
 
Line 1,662 ⟶ 1,787:
 
{{works with|Ruby|2.0+}}
<langsyntaxhighlight lang="ruby">require 'fiddle/import'
 
module FakeImgLib
Line 1,681 ⟶ 1,806:
 
handle = FakeImgLib.openimage("path/to/image")
puts "opened with handle #{handle}"</langsyntaxhighlight>
 
The next script tries to use ImageMagick. First, it tries [https://rmagick.github.io/ rmagick] from RubyGems. If that library is missing, it tries to use [http://wiki.github.com/ffi/ffi ffi] from RubyGems to call C functions in ImageMagick. (FFI is an alternative to Fiddle). If that doesn't work, it falls back to code that only handles PNG images.
Line 1,688 ⟶ 1,813:
{{libheader|RubyGems}}
{{works with|Ruby|1.9+}}
<langsyntaxhighlight lang="ruby"># This script shows the width x height of some images.
# Example:
# $ ruby imsize.rb dwarf-vs-elf.png swedish-chef.jpg
Line 1,759 ⟶ 1,884:
end
end
exit status</langsyntaxhighlight>
 
=={{header|Rust}}==
Line 1,765 ⟶ 1,890:
 
===Unix===
<langsyntaxhighlight lang="rust">#![allow(unused_unsafe)]
extern crate libc;
 
Line 1,802 ⟶ 1,927:
fn builtin_cos(x: c_double) -> c_double {
x.cos()
}</langsyntaxhighlight>
 
=={{header|Scala}}==
===Windows===
====Get free disk space====
{{libheader|net.java.dev.sna.SNA}}
<langsyntaxhighlight Scalalang="scala">import net.java.dev.sna.SNA
import com.sun.jna.ptr.IntByReference
 
Line 1,833 ⟶ 1,957:
println(f"'$disk%s' ($ok%s): sectors/cluster: ${spc.getValue}%d, bytes/sector: ${bps.getValue}%d, " +
f" free-clusters: ${fc.getValue}%d, total/clusters: ${tc.getValue}%d%n")
}}</langsyntaxhighlight>
 
=={{header|Smalltalk}}==
{{works with|GNU Smalltalk}}
The code tries to load the <tt>fakeimglib</tt> (cfr [[Call function in shared library#C|C example]]); if it succeed, the symbol <tt>openimage</tt> will exist, and will be called; otherwise, it is executed an "internal" code for <tt>openimage</tt>. In this example return code of the function of the library is ignored (<tt>ValueHolder null</tt>)
<langsyntaxhighlight lang="smalltalk">DLD addLibrary: 'fakeimglib'.
 
Object subclass: ExtLib [
Line 1,851 ⟶ 1,974:
].
 
ExtLib openimage: 'test.png'.</langsyntaxhighlight>
=={{header|SNOBOL4}}==
{{works with|CSNOBOL4}}
This code loads the <tt>libm</tt> library into the variable <tt>ffi_m</tt> and binds the <tt>hypot()</tt> function to the variable <tt>ffi_m_hypot</tt>. (The variable names are arbitrary.) It then declares a SNOBOL4 function called <tt>hypot()</tt> which takes two <tt>double</tt>s as arguments and returns a <tt>double</tt>, binding this name to the <tt>ffi_m_hypot</tt> object returned earlier. It then outputs four hypotenuse calculations using those values.
<syntaxhighlight lang="snobol4">-INCLUDE 'ffi.sno'
 
ffi_m = FFI_DLOPEN('/usr/lib/x86_64-linux-gnu/libm.so')
ffi_m_hypot = FFI_DLSYM(ffi_m, 'hypot')
DEFINE_FFI('hypot(double,double)double', ffi_m_hypot)
 
OUTPUT = hypot(1,2)
OUTPUT = hypot(2,3)
OUTPUT = hypot(3,4)
OUTPUT = hypot(4,5)
 
END</syntaxhighlight>
 
Execution looks like this:
 
<pre>$ snobol4 ffitest.sno
2.23606797749979
3.60555127546399
5.
6.40312423743285</pre>
=={{header|Tcl}}==
{{libheader|Ffidl}}
<langsyntaxhighlight Tcllang="tcl">package require Ffidl
 
if {[catch {
Line 1,862 ⟶ 2,007:
# Create the OpenImage command by other means here...
}
set handle [OpenImage "/the/file/name"]</langsyntaxhighlight>
Note that if the library is appropriately set up with the correct entry function, it can be accessed directly with <code>load</code> which will cause it to register a Tcl command for the functionality it exports. [http://www.swig.org SWIG] can be used to automatically generate the interface code. Alternatively, [[:Category:Critcl|critcl]] can be used to allow writing glue [[C]] code directly embedded within a Tcl script.
 
With this many ways to perform the call, the best approach often depends on the size and complexity of the API being mapped. SWIG excels at large APIs, Ffidl is better when you just want to call a particular simple function, and critcl handles complex cases (callbacks, etc.) better than the other two.
 
=={{header|TXR}}==
 
Line 1,899 ⟶ 2,043:
 
The <code>nil</code> argument in the <code>with-dyn-lib</code> macro causes the underlying implementation to call <code>dlopen(NULL)</code> to get access to the dynamic symbols available in the executable. We can use the name of a shared library instead, or a handle from TXR's <code>dlopen</code> library function.
 
=={{header|Ursala}}==
When abs(x) is evaluated, a run time check is performed for the
Line 1,905 ⟶ 2,048:
and if found, it is used. If not, the user defined replacement
function is invoked.
<langsyntaxhighlight Ursalalang="ursala">#import std
#import flo
 
my_replacement = fleq/0.?/~& negative
 
abs = math.|fabs my_replacement</langsyntaxhighlight>
 
=={{header|VBA}}==
Here is an example using a Fortran function compiled as a DLL, using Intel Fortran.
Line 1,917 ⟶ 2,059:
First the DLL. Compile with '''ifort /dll vbafun.f90'''. The DLL must be in a directory in the PATH environment variable. Notice that for 32 bits VBA, DLL functions must be STDCALL, and not CDECL (the default with Intel Fortran). In 64 bits, there is only one calling convention, so it's not a problem anymore.
 
<langsyntaxhighlight lang="fortran">function ffun(x, y)
implicit none
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE :: ffun
double precision :: x, y, ffun
ffun = x + y * y
end function</langsyntaxhighlight>
 
Here is a VBA subroutine using the DLL
 
<langsyntaxhighlight lang="vb">Option Explicit
Declare Function ffun Lib "vbafun" (ByRef x As Double, ByRef y As Double) As Double
Sub Test()
Line 1,933 ⟶ 2,075:
y = 10#
Debug.Print ffun(x, y)
End Sub</langsyntaxhighlight>
=={{header|Wren}}==
{{trans|C}}
An embedded program so we can ask the C host to call the shared library function for us.
<syntaxhighlight lang="wren">/* Call_a_function_in_a_shared_library.wren */
 
var RTLD_LAZY = 1
 
foreign class DL {
construct open(file, mode) {}
 
foreign call(symbol, arg)
 
foreign close()
}
 
class My {
static openimage(s) {
System.print("internal openimage opens %(s)...")
if (!__handle) __handle = 0
__handle = __handle + 1
return __handle - 1
}
}
 
var file = "fake.img"
var imglib = DL.open("./fakeimglib.so", RTLD_LAZY)
var imghandle = (imglib != null) ? imglib.call("openimage", file) : My.openimage(file)
System.print("opened with handle %(imghandle)")
if (imglib != null) imglib.close()</syntaxhighlight>
<br>
We also need to create the shared library, fakeimglib.so, and place it in the current directory.
<syntaxhighlight lang="c">/*
gcc -c -fpic fakeimglib.c
gcc -shared fakeimglib.o -o fakeimglib.so
*/
#include <stdio.h>
 
int openimage(const char *s) {
static int handle = 100;
fprintf(stderr, "opening %s\n", s);
return handle++;
}</syntaxhighlight>
<br>
Finally, we embed the Wren script in the following C program, compile and run it:
<syntaxhighlight lang="c">/* gcc Call_a_function_in_a_shared_library.c -o Call_a_function_in_a_shared_library -ldl -lwren -lm */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include "wren.h"
 
/* C <=> Wren interface functions */
 
void C_dlAllocate(WrenVM* vm) {
const char *file = wrenGetSlotString(vm, 1);
int mode = (int)wrenGetSlotDouble(vm, 2);
void *imglib = dlopen(file, mode);
if (imglib == NULL) wrenSetSlotNull(vm, 0);
void** pimglib = (void**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(void*));
*pimglib = imglib;
}
 
void C_call(WrenVM* vm) {
void *imglib = *(void**)wrenGetSlotForeign(vm, 0);
const char *symbol = wrenGetSlotString(vm, 1);
const char *arg = wrenGetSlotString(vm, 2);
int (*extopenimage)(const char *);
extopenimage = dlsym(imglib, symbol);
int imghandle = extopenimage(arg);
wrenSetSlotDouble(vm, 0, (double)imghandle);
}
 
void C_close(WrenVM* vm) {
void *imglib = *(void**)wrenGetSlotForeign(vm, 0);
dlclose(imglib);
}
 
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.finalize = NULL;
if (strcmp(module, "main") == 0) {
if (strcmp(className, "DL") == 0) {
methods.allocate = C_dlAllocate;
}
}
return methods;
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "DL") == 0) {
if (!isStatic && strcmp(signature, "call(_,_)") == 0) return C_call;
if (!isStatic && strcmp(signature, "close()") == 0) return C_close;
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
 
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignClassFn = &bindForeignClass;
config.bindForeignMethodFn = &bindForeignMethod;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "Call_a_function_in_a_shared_library.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</syntaxhighlight>
 
{{out}}
<pre>
Same as C example depending on whether fakeimglib.so is present in the current directory or not.
</pre>
 
=={{header|X86-64 Assembly}}==
===UASM 2.52===
<syntaxhighlight lang="asm">
option casemap:none
 
windows64 equ 1
linux64 equ 3
 
ifndef __LIB_CLASS__
__LIB_CLASS__ equ 1
 
if @Platform eq windows64
option dllimport:<kernel32>
HeapAlloc proto :qword, :dword, :qword
HeapFree proto :qword, :dword, :qword
ExitProcess proto :dword
GetProcessHeap proto
LoadLibraryA proto :qword
FreeLibrary proto :qword
GetProcAddress proto :qword, :qword
option dllimport:none
exit equ ExitProcess
dlsym equ GetProcAddress
dlclose equ FreeLibrary
elseif @Platform eq linux64
malloc proto :qword
free proto :qword
exit proto :dword
dlclose proto :qword
dlopen proto :qword, :dword
dlsym proto :qword, :qword
endif
printf proto :qword, :vararg
 
CLASS libldr
CMETHOD getproc
ENDMETHODS
libname db 100 dup (0)
plib dq ?
ENDCLASS
 
METHOD libldr, Init, <VOIDARG>, <>, library:qword, namelen:qword
mov rbx, thisPtr
assume rbx:ptr libldr
.if library != 0
mov rcx, namelen
mov rsi, library
lea rdi, [rbx].libname
rep movsb
if @Platform eq windows64
invoke LoadLibraryA, addr [rbx].libname
.if rax == 0
invoke printf, CSTR("--> Failed to load library",10)
.else
mov [rbx].plib, rax
.endif
elseif @Platform eq linux64
invoke dlopen, addr [rbx].libname, 1
.if rax == 0
lea rax, [rbx].libname
invoke printf, CSTR("--> Failed to load library %s",10), rax
.else
mov [rbx].plib, rax
.endif
endif
.else
invoke printf, CSTR("--> Library name to load required..",10)
.endif
mov rax, rbx
assume rbx:nothing
ret
ENDMETHOD
 
METHOD libldr, getproc, <VOIDARG>, <>, func:qword
local tmp:qword
mov tmp, func
;; Just return RAX..
invoke dlsym, [thisPtr].libldr.plib, tmp
ret
ENDMETHOD
 
METHOD libldr, Destroy, <VOIDARG>, <>
mov rbx, thisPtr
assume rbx:ptr libldr
.if [rbx].plib != 0
invoke dlclose, [rbx].plib
.endif
assume rbx:nothing
ret
ENDMETHOD
endif
 
.data
LibName db "./somelib.l",0
 
.code
main proc
local ldr:ptr libldr
invoke printf, CSTR("--> Loading %s .. ",10), addr LibName
mov ldr, _NEW(libldr, addr LibName, sizeof(LibName))
ldr->getproc(CSTR("disappointment"))
.if rax == 0
lea rax, idisappointment
.endif
call rax
_DELETE(ldr)
invoke exit, 0
ret
main endp
 
idisappointment:
push rbp
mov rbp, rsp
invoke printf, CSTR("--> Well this is a internal disappointment..",10)
pop rbp
mov rax, 0
ret
end
</syntaxhighlight>
It's worth pointing out that under linux, dlopen CAN return NULL WITHOUT it being an error. One SHOULD call dlerror() to check for actual errors.
{{out}}
<pre>
--> Loading ./somelib.l ..
--> Well this is a external disappointment..
And on failure...
--> Loading ./somelib.l ..
--> Failed to load library ./somelib.l
--> Well this is a internal disappointment..
</pre>
=={{header|zkl}}==
In zkl, extensions/new objects are written in C as shared libraries. For example, big nums are implemented as a small glue library in front of GMP:
<langsyntaxhighlight lang="zkl">var BN=Import("zklBigNum");
BN(1)+2 //--> BN(3)</langsyntaxhighlight>
and it "just works" as all objects are "the same" whether statically or dynamically linked.
 
 
{{omit from|Batch File|Except for rundll32.exe (which is rather limited) there is no way of calling an external function}}
{{omit from|EasyLang|Libraries do not exist in EasyLang}}
{{omit from|GUISS}}
{{omit from|M4}}
{{omit from|Maxima}}
{{omit from|ML/I}}
{{omit from|Retro|No FFI}}
{{omit from|Scheme|No standard FFI, due to no standard implementation.}}
{{omit from|TI-83 BASIC|Does not have a standard FFI.}}
{{omit from|TI-89 BASIC|Does not have a standard FFI.}}
{{omit from|Scheme|No standard FFI, due to no standard implementation.}}
{{omit from|Retro|No FFI}}
 
[[Category:Functions and subroutines]]
9,476

edits