1. Pass C double to Eu shared library

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

new topic     » topic index » view message » categorize

2. Re: Pass C double to Eu shared library

Jerome said...

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; 
} 
new topic     » goto parent     » topic index » view message » categorize

3. Re: Pass C double to Eu shared library

Jerome said...

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

new topic     » goto parent     » topic index » view message » categorize

4. Re: Pass C double to Eu shared library

mattlewis said...

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

new topic     » goto parent     » topic index » view message » categorize

5. Re: Pass C double to Eu shared library

mattlewis said...
mattlewis said...

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

new topic     » goto parent     » topic index » view message » categorize

6. Re: Pass C double to Eu shared library

mattlewis said...

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

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu