Call a function in a shared library: Difference between revisions
(added c#) |
(smalltalk) |
||
Line 89:
# Rest of program</lang>
=={{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>)
<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: 'prova'.</lang>
|
Revision as of 23:29, 17 April 2009
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.
C
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>
- include <stdlib.h>
- 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"
- Rest of program</lang>
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: 'prova'.</lang>