1. Pass C double to Eu shared library
- Posted by Jerome May 11, 2012
- 1559 views
I have a shared library made with EU 4 that I would like to access from C by passing an array of doubles. Looking through the manual I found this:
Euphoria shared dynamically loading library can also be used by C programs as long as only 31-bit integer values are exchanged. If a 32-bit pointer or integer must be passed, and you have the source to the C program, you could pass the value in two separate 16-bit integer arguments (upper 16 bits and lower 16 bits), and then combine the values in the Euphoria routine into the desired 32-bit atom.
Is there a clean way to do this?
My current code is essentially the following:
-- Eu Code export function MyFunc(sequence x) ? x end function
// C Code extern MyFunc(double x[]) int main() { double x[4] = {1.1,2.2,3.3,4.4}; MyFunc(x); return 0; }
Thanks,
Ira
2. Re: Pass C double to Eu shared library
- Posted by jimcbrown (admin) May 12, 2012
- 1511 views
I have a shared library made with EU 4 that I would like to access from C by passing an array of doubles. Looking through the manual I found this:
Euphoria shared dynamically loading library can also be used by C programs as long as only 31-bit integer values are exchanged. If a 32-bit pointer or integer must be passed, and you have the source to the C program, you could pass the value in two separate 16-bit integer arguments (upper 16 bits and lower 16 bits), and then combine the values in the Euphoria routine into the desired 32-bit atom.
Is there a clean way to do this?
My current code is essentially the following:
-- Eu Code export function MyFunc(sequence x) ? x end function
// C Code extern MyFunc(double x[]) int main() { double x[4] = {1.1,2.2,3.3,4.4}; MyFunc(x); return 0; }
Thanks,
Ira
On the Euphoria side,
-- Eu Code export function MyFunc(integer a, integer b, integer len) -- preamble to handle conversion atom p = (a * 65536) + b sequence x = {} for i = 0 to (len-1)*8 by 8 do sequence d = peek({p+i, 8}) x &= float64_to_atom(d) done -- end preamble ? x end function
(Sadly, 4.0 seems to lack a peek_float64_array(). Otherwise we could do this:
-- Eu Code export function MyFunc(integer a, integer b, integer len) -- preamble to handle conversion atom p = (a * 65536) + b sequence x = peek_float64_array(p, len) -- end preamble ? x end function
)
On the C side,
// C Code extern void MyFunc(int a, int b, int len) int main() { double x[4] = {1.1,2.2,3.3,4.4}; intptr_t d, a, b; d = (intptr_t)x; b = d & 0xFFFF; a = d & 0xFFFF0000; a = a >> 16; MyFunc(a, b, 4); return 0; }
Or even,
// C Code extern void MyFunc(int a, int b, int len) void MyFuncWrapper(double x[], int len) { intptr_t d, a, b; d = (intptr_t)x; b = d & 0xFFFF; a = d & 0xFFFF0000; a = a >> 16; MyFunc(a, b, 4); } int main() { double x[4] = {1.1,2.2,3.3,4.4}; MyFuncWrapper(x, 4); return 0; }
3. Re: Pass C double to Eu shared library
- Posted by mattlewis (admin) May 12, 2012
- 1547 views
I have a shared library made with EU 4 that I would like to access from C by passing an array of doubles. Looking through the manual I found this:
Euphoria shared dynamically loading library can also be used by C programs as long as only 31-bit integer values are exchanged. If a 32-bit pointer or integer must be passed, and you have the source to the C program, you could pass the value in two separate 16-bit integer arguments (upper 16 bits and lower 16 bits), and then combine the values in the Euphoria routine into the desired 32-bit atom.
Is there a clean way to do this?
My current code is essentially the following:
-- Eu Code export function MyFunc(sequence x) ? x end function
// C Code extern MyFunc(double x[]) int main() { double x[4] = {1.1,2.2,3.3,4.4}; MyFunc(x); return 0; }
I think the cleanest way is to use Use 32-bit Integers In Translated DLLs. It's kind of a hack, but I think it's the cleanest solution. It requires special wrappers that the external world should call, and it modifies your translated source.
It seems to almost work with 4.0.4. This required some updates to make_atom.exw for 4.0. And I modified test.exw to open the .so that I created on Linux, instead of a Windows dll.
$ euc -makefile -so test.ew Translating code, pass: 1 2 3 generating 4.c files were created. To build your project, type make -f test.mak $ eui make_atom.exw ~/eu/32bits$ make -f test.mak gcc -fomit-frame-pointer -fPIC -c -w -fsigned-char -O2 -m64 -I/usr/local/share/euphoria -ffast-math init-.c -o init-.o gcc -fomit-frame-pointer -fPIC -c -w -fsigned-char -O2 -m64 -I/usr/local/share/euphoria -ffast-math test.c -o test.o gcc -fomit-frame-pointer -fPIC -c -w -fsigned-char -O2 -m64 -I/usr/local/share/euphoria -ffast-math main-.c -o main-.o gcc -fomit-frame-pointer -fPIC -c -w -fsigned-char -O2 -m64 -I/usr/local/share/euphoria -ffast-math make_atom.c -o make_atom.o gcc -o test.so init-.o test.o main-.o make_atom.o /usr/local/lib/euso.a -m64 -shared -ldl -lm -lpthread $ eui test Passing signed integer: -225 Signed( -225 ) Passing unsigned integer: 4294967071 Unsigned( 4294967071 ) Done. Press any key to exit.
Matt
4. Re: Pass C double to Eu shared library
- Posted by mattlewis (admin) May 12, 2012
- 1478 views
I think the cleanest way is to use Use 32-bit Integers In Translated DLLs. It's kind of a hack, but I think it's the cleanest solution. It requires special wrappers that the external world should call, and it modifies your translated source.
It seems to almost work with 4.0.4. This required some updates to make_atom.exw for 4.0. And I modified test.exw to open the .so that I created on Linux, instead of a Windows dll.
I made some updates, and it seems to be working with 4.0 and 4.1, including with 64-bits. I created a bitbucket repository for the code.
Matt
5. Re: Pass C double to Eu shared library
- Posted by mattlewis (admin) May 13, 2012
- 1512 views
I think the cleanest way is to use Use 32-bit Integers In Translated DLLs. It's kind of a hack, but I think it's the cleanest solution. It requires special wrappers that the external world should call, and it modifies your translated source.
It seems to almost work with 4.0.4. This required some updates to make_atom.exw for 4.0. And I modified test.exw to open the .so that I created on Linux, instead of a Windows dll.
I made some updates, and it seems to be working with 4.0 and 4.1, including with 64-bits. I created a bitbucket repository for the code.
Oops. I had forgotten to make the repository public. I've fixed that now, so it should be publicly visible.
Matt
6. Re: Pass C double to Eu shared library
- Posted by Jerome May 14, 2012
- 1472 views
I think the cleanest way is to use Use 32-bit Integers In Translated DLLs. It's kind of a hack, but I think it's the cleanest solution. It requires special wrappers that the external world should call, and it modifies your translated source.
Thanks Jim and Matt! I've implemented Jim's method, and it works great. Matt, I'm also going to to check out 32-bit integers for future projects. Currently, I'm porting a large chunk of Matlab code to see what type of speed improvements I can get.
Thanks,
Ira