1. RE: Using shared objects
>From: Ron Weidner <guest at RapidEuphoria.com>
>Reply-To: EUforum at topica.com
>To: EUforum at topica.com
>Subject: Using shared objects
>Date: Thu, 02 Jun 2005 13:29:46 -0700
>
>posted by: Ron Weidner <nova812 at hotmail.com>
>
>I have some shared object written in C. Below is the code.
>What I want is to write a euphoria include that maps the
>shared object to euphoria.
>
You will probably need to rewrite the C code slightly, like so:
#include <stdio.h>
#define NUM_DOG 10
__declspec(dllexport) void __stdcall mush(char**, int);
__declspec(dllexport) int __stdcall bark();
__declspec(dllexport) void __stdcall mush(char* dogs[], int len)
{
int i;
printf("Number of dogs: %d \n", len );
for (i=0; i < len; i++)
{
printf("Dog named: %s starts mushing...\n", dogs[i]);
}
}
__declspec(dllexport) int __stdcall bark()
{
return 1;
}
Note that the __declspec and the __stdcall are Windows-specific, and you
would probably need to use something different in GCC to make sure a
function name is exported and not mangled.
The following can be put in your dog.e:
include dll.e
include machine.e
atom dogLib
if platform() = 2 then
dogLib = open_dll("dog.dll")
elsif platform() = 3 then
-- You would need to use "./dog.so" here if dog.so is in the current
directory...
dogLib = open_dll("dog.so")
end if
constant
mush_ = define_c_proc(dogLib, "mush", {C_POINTER, C_INT}),
bark_ = define_c_func(dogLib, "bark", {}, C_INT)
global procedure mush(sequence p)
atom lp
sequence lps
integer len
len = length(p)
lp = allocate(len * 4)
lps = repeat(0, len)
for loop = 1 to len do
lps[loop] = allocate_string(p[loop])
end for
poke4(lp, lps)
c_proc(mush_, {lp, len})
for loop = 1 to len do
free(lps[loop])
end for
free(lp)
end procedure
global function bark()
return c_func(bark_, {})
end function
And then of course, you can run your program like you said.
>include dog.e
>if atom(bark()) then
> mush({"scooby", "dino", "astro", "spike"}) --notice the absence of arg 2
>end if
>
></eucode>
{{{
>
~[ WingZone ]~
http://wingzone.tripod.com/
2. RE: Using shared objects
Thank you! Your code worked perfectly.
I didn't test on Windows. (I don't have a windows box
at the moment to test on) So I'm not sure about the
whole bit about ...
__declspec(dllexport) void __stdcall
But, if I had to guess, (and this is only a guess) you
should only need that stuff if and only if you are
using a c++ compiler as opposed to a c compiler. I
compiled the dog.so using GCC which is a C compiler
and didn't need to make any changes to the C code. I
suspect if I compiled using g++, I would need to
make some changes.
I studied your code, cross referenced it with the eu docs,
and now I'm goint to take a crack at explaining it. Let
me know if I'm close.
atom dogLib -- used like a pointer
-- You would need to use "./dog.so" here if dog.so
-- is actually in the current directory or you could
-- use ./somedir/dog.so if the .so is nested deeper
-- relative to the current directory
-- load the dll and return a pointer to its mem location
dogLib = open_dll("./dog.so")
-- This is like porting the C header files to Euphoria
constant
mush_ = define_c_proc(dogLib, "mush", {C_POINTER, C_INT}),
bark_ = define_c_func(dogLib, "bark", {}, C_INT)
global procedure mush(sequence p)
atom lp -- used as a pointer
sequence lps -- used as an array of pointers
integer len -- len of p where p is expected to be a sequence of
sequences
len = length(p)
-- create a pointer to a block of mem 4 bytes long * the len of p
-- the reason for 4 bytes is because that's the size of a pointer
lp = allocate(len * 4)
-- delete any garbage in the memory locations
lps = repeat(0, len)
-- start making pointers to each sequence in p
for loop = 1 to len do
-- allocate enough mem for p[loop] + 1, strcpy the val
-- in p[loop] & "\0" to that location and return a
-- pointer to it.
lps[loop] = allocate_string(p[loop])
end for
-- poke4(atom where_p, object what)
-- put the 4 pointers just created into the lp mem location
poke4(lp, lps)
-- call the c function (procedure since the C return val is void)
c_proc(mush_, {lp, len})
-- look ma... mem leaks in euphoria are posible. :)
for loop = 1 to len do
free(lps[loop]) -- free the strings
end for
free(lp) -- free the mem storing pointers to the strings
end procedure -- how'd I do??
global function bark()
return c_func(bark_, {})
end function
3. RE: Using shared objects
Ron Weidner wrote:
> }}}
<eucode>
> atom dogLib -- used like a pointer
> -- You would need to use "./dog.so" here if dog.so
> -- is actually in the current directory or you could
> -- use ./somedir/dog.so if the .so is nested deeper
> -- relative to the current directory
>
> -- load the dll and return a pointer to its mem location
> dogLib = open_dll("./dog.so")
>
> -- This is like porting the C header files to Euphoria
> constant
> mush_ = define_c_proc(dogLib, "mush", {C_POINTER, C_INT}),
> bark_ = define_c_func(dogLib, "bark", {}, C_INT)
>
> global procedure mush(sequence p)
> atom lp -- used as a pointer
> sequence lps -- used as an array of pointers
> integer len -- len of p where p is expected to be a sequence of
> sequences
> len = length(p)
>
> -- create a pointer to a block of mem 4 bytes long * the len of p
> -- the reason for 4 bytes is because that's the size of a pointer
> lp = allocate(len * 4)
>
> -- delete any garbage in the memory locations
> lps = repeat(0, len)
</eucode>
{{{
lps = repeat(0,len) doesn't delete any garbage in the memory location, it
creates
a euphoria sequence of len, filled with 0's. In other words, if len is 4, you
get lps = {0,0,0,0}
> -- start making pointers to each sequence in p
> for loop = 1 to len do
>
> -- allocate enough mem for p[loop] + 1, strcpy the val
> -- in p[loop] & "\0" to that location and return a
> -- pointer to it.
> lps[loop] = allocate_string(p[loop])
>
> end for
>
> -- poke4(atom where_p, object what)
> -- put the 4 pointers just created into the lp mem location
> poke4(lp, lps)
>
> -- call the c function (procedure since the C return val is void)
> c_proc(mush_, {lp, len})
>
> -- look ma... mem leaks in euphoria are posible. :)
> for loop = 1 to len do
> free(lps[loop]) -- free the strings
> end for
Memory Leaks are possible in Euphoria, yes. But Memory leaks are only
possible during the execution of Euphoria, at the end of the execution of
your Euphoria program, any memory allocated BY the Interpreter, will get
freed automatically. Any memory allocated by External C libraries, must
maintain their own memory cleanup, as Euphoria has no clue about the
memory allocated by them.
> free(lp) -- free the mem storing pointers to the strings
> end procedure -- how'd I do??
>
> global function bark()
> return c_func(bark_, {})
> end function
>
> <font color="#330033">
</font>
Other then the two points I made, you are exactly right on the money for the
rest of the stuff.
Mario Steele
http://enchantedblade.trilake.net
Attaining World Dominiation, one byte at a time...