Call a function in a shared library: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 105: Line 105:
=={{header|Smalltalk}}==
=={{header|Smalltalk}}==
{{works with|GNU 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>)
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>)



Revision as of 10:36, 30 May 2009

Task
Call a function in a shared library
You are encouraged to solve this task according to the task description, using any language you may know.

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.

AutoHotkey

Works with: [AutoHotkey.dll]


dllhost.ahk <lang AutoHotkey> ahkdll := DllCall("LoadLibrary", "str", "AutoHotkey.dll") clientHandle := DllCall("AutoHotkey\ahkdll", "str", "dllclient.ahk", "str" , "", "str", "parameter1 parameter2", "Cdecl Int") </lang> dllclient.ahk <lang AutoHotkey> Msgbox, hello from client </lang>

C

Works with: POSIX version .1-2001

Tested with gcc on a GNU/Linux system (on GNU/Linux dl* functions are available linking to libdl, i.e. with -ldl option)

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <dlfcn.h>

int myopenimage(char *in) {

 static int handle=0;
 fprintf(stderr, "internal openimage opens %s...\n", in);
 return handle++;

}

int main() {

 void *imglib;
 int (*extopenimage)(char *);
 int imghandle;
 imglib = dlopen("./fakeimglib.so", RTLD_LAZY);
 if ( imglib != NULL ) {
   /* extopenimage = (int (*)(char *))dlsym(imglib,...)
      "man dlopen" says that C99 standard leaves casting from
      "void *" to a function pointer undefined. The following is the
      POSIX.1-2003 workaround found in man */
   *(void **)(&extopenimage) = dlsym(imglib, "openimage");
   /* the following works with gcc, gives no warning even with
      -Wall -std=c99 -pedantic options... :D */
   /* extopenimage = dlsym(imglib, "openimage"); */
   imghandle = extopenimage("fake.img");
 } else {
   imghandle = myopenimage("fake.img");
 }
 printf("opened with handle %d\n", imghandle);
 /* ... */
 if (imglib != NULL ) dlclose(imglib);
 return EXIT_SUCCESS;

}</lang>

The fake fakeimglib.so code is

<lang c>#include <stdio.h> /* gcc -shared -nostartfiles fakeimglib.c -o fakeimglib.so */ int openimage(char *s) {

 static int handle = 100;
 fprintf(stderr, "opening %s\n", s);
 return handle++;

}</lang>

When the library fakeimglib.c exists in the current directory (this choice is senseful only for testing purposes), the output is:

opening fake.img
opened with handle 100

otherwise the output is:

internal openimage opens fake.img...
opened with handle 0

C#

In Windows.

<lang csharp>using System.Runtime.InteropServices;

class Program {

   [DllImport("fakelib.dll")]
   public static extern int fakefunction(int args);
   static void Main(string[] args) {
       int r = fakefunction(10);
   }

}</lang>

Python

The import statement can be done in a try/except block <lang python>try:

   import psyco
   psyco.full()
   print "# With psyco JIT compiler"

except:

   print "# Without psyco JIT compiler"
  1. Rest of program</lang>

Smalltalk

Works with: GNU Smalltalk

The code tries to load the fakeimglib (cfr C example); if it succeed, the symbol openimage will exist, and will be called; otherwise, it is executed an "internal" code for openimage. In this example return code of the function of the library is ignored (ValueHolder null)

<lang smalltalk>DLD addLibrary: 'fakeimglib'.

Object subclass: ExtLib [

 ExtLib class >> openimage: aString [
   (CFunctionDescriptor isFunction: 'openimage')
   ifTrue: [
      (CFunctionDescriptor for: 'openimage'
                           returning: #int
                           withArgs: #( #string ) ) callInto: (ValueHolder null).
   ] ifFalse: [ ('internal open image %1' % { aString }) displayNl ]
 ]

].

ExtLib openimage: 'test.png'.</lang>

Tcl

Library: Ffidl

<lang Tcl>package require Ffidl

if {[catch {

   ffidl::callout OpenImage {pointer-utf8} int [ffidl::symbol fakeimglib.so openimage]

}]} then {

   # Create the OpenImage command by other means here...

} set handle [OpenImage "/the/file/name"]</lang> Note that if the library is appropriately set up with the correct entry function, it can be accessed directly with load which will cause it to register a Tcl command for the functionality it exports. SWIG can be used to automatically generate the interface code.