1. Phix: cffi.e

I looked at raylib for openeuphoria. Now I'm thinking about how and whether I can use this library with phix.

Can someone tell me how to use this code with phix with cffi.e for example:
In the functioncall Vector2 is not a pointer to a structure but the structure itself.
with ffi.e for openeuphoria this seems to work but i have no idea how to implement this with phix.

/* from raylib.h */ 
 
// Vector2, 2 components 
typedef struct Vector2 { 
    float x;                // Vector x component 
    float y;                // Vector y component 
} Vector2; 
 
RLAPI void DrawCircleV(Vector2 center, float radius, Color color);  
maybe i just haven't found it in the documentation yet.

Thank you
Andreas

new topic     » topic index » view message » categorize

2. Re: Phix: cffi.e

andreasWagner said...

I looked at raylib for openeuphoria. Now I'm thinking about how and whether I can use this library with phix.

Can someone tell me how to use this code with phix with cffi.e for example:
In the functioncall Vector2 is not a pointer to a structure but the structure itself.
with ffi.e for openeuphoria this seems to work but i have no idea how to implement this with phix.

/* from raylib.h */ 
 
// Vector2, 2 components 
typedef struct Vector2 { 
    float x;                // Vector x component 
    float y;                // Vector y component 
} Vector2; 
 
RLAPI void DrawCircleV(Vector2 center, float radius, Color color);  
maybe i just haven't found it in the documentation yet.

Thank you
Andreas

Well I'm not sure how you'd wrap it in Phix, but I assume it'd be similar to how it is wrapped in OE.

include std/ffi.e --the FFI library 
 
--defines a struct we can use Vector2, we declare the x and y members as floats, as they are in the C library. 
public constant VECTOR2 = define_c_struct({ 
  C_FLOAT, --x 
  C_FLOAT 
}) 
 
--defines a struct of color, where members r,g,b,a are unsigned chars in the C library 
public constant COLOR = define_c_struct({ 
  C_UCHAR, --r 
  C_UCHAR, --g 
  C_UCHAR, --b 
  C_UCHAR  --a 
}) 
 
public constant xDrawCircleV = define_c_proc(ray,"+DrawCircleV",{VECTOR2,C_FLOAT,COLOR}) 
 
public procedure DrawCircleV(sequence vector2,atom radius,sequence color) 
  c_proc(xDrawCircleV,{vector2,radius,color}) 
end procedure 
 
--Then you can access the members like a sequence in an array 
 
DrawCircle({10,10},20,{255,255,255,255}) --Draws a circle at x: 10 and y: 10, radius: 20 and color values set 255,255,255,255 
 

I hope that helps.

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

3. Re: Phix: cffi.e

In Phix I'd start with something like this (NB completely untested)

include cffi.e 
constant t_Vector2 = """ 

typedef struct Vector2 {  
    float x;                // Vector x component  
    float y;                // Vector y component  
} Vector2; """ 

constant idVector2 = define_struct(t_Vector2), 
         pVector2 = allocate_struct(idVector2) 
  
-- (you might get away with passing/need to pass #RRGGBBAA values directly, 
--  and/or allocate(4) and poke4(said) might be much neater...) 
constant t_Color = """ 

typedef struct Color { 
    unsigned char r;        // Color red value 
    unsigned char g;        // Color green value 
    unsigned char b;        // Color blue value 
    unsigned char a;        // Color alpha value 
} Color;""" 
constant idColor = define_struct(t_Color), 
         pColor = allocate_struct(idColor) 
 
-- I can tell you this kind of thing simply won't work: 
--constant xDrawCircleV = define_c_proc(ray,"+DrawCircleV",{VECTOR2,C_FLOAT,COLOR})  
-- instead: 
local constant xDrawCircleV = define_c_proc(ray,"+DrawCircleV",{C_PTR,C_FLOAT,C_PTR})  
  
global procedure DrawCircleV(sequence vector2, atom radius, sequence color)  
    atom {x,y} = vector2 
    set_struct_field(idVector2,pVector2,"x",x) 
    set_struct_field(idVector2,pVector2,"y",y) 
    integer {r,g,b,a} = color 
    set_struct_field(idColor,pColor,"r",r) 
    set_struct_field(idColor,pColor,"g",g) 
    set_struct_field(idColor,pColor,"b",b) 
    set_struct_field(idColor,pColor,"a",a) 
    c_proc(xDrawCircleV,{pVector2,radius,pColor})  
end procedure  
 
-- if an alpha of 255 means fully transparent, this won't show anything: 
DrawCircleV({10,10},20,{255,255,255,255}) 
 
new topic     » goto parent     » topic index » view message » categorize

4. Re: Phix: cffi.e

Icy_Viking said...

Well I'm not sure how you'd wrap it in Phix, but I assume it'd be similar to how it is wrapped in OE.

include std/ffi.e --the FFI library 
[...] 
  

Thanks for your effort, but I think it takes a lot of work to port ffi.e to phix.

Thanks a lot

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

5. Re: Phix: cffi.e

petelomax said...

In Phix I'd start with something like this (NB completely untested)

include cffi.e 
[...] 
 
-- I can tell you this kind of thing simply won't work: 
--constant xDrawCircleV = define_c_proc(ray,"+DrawCircleV",{VECTOR2,C_FLOAT,COLOR})  
-- instead: 
local constant xDrawCircleV = define_c_proc(ray,"+DrawCircleV",{C_PTR,C_FLOAT,C_PTR})  
  
[...] 

Thank you very much for the effort. My knowledge of the C programming language is very modest, but this will probably not work.

RLAPI void DrawCircleV(Vector2 center, float radius, Color color);   

As I understand it:

This Function Call needs the structur passed as Value, your code passes it as reference (C_PTR,Pointer)

many thanks

Andreas

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

6. Re: Phix: cffi.e

andreasWagner said...

This Function Call needs the structur passed as Value, your code passes it as reference (C_PTR,Pointer)

Hmm, maybe something like this would work (where color is a single #RRGGBBAA value):

local constant xDrawCircleV = define_c_proc(ray,"+DrawCircleV",{C_FLOAT,C_FLOAT,C_FLOAT,C_DWORD})  
c_proc(xDrawCircleV,{x,y,radius,color}) 

If you can make a small working C program, or better yet FASM which I've done myself more than once, then disassemble it with OllyDbg, fdbg, or even Phix's own filedump.exw,
then even should c_proc be unable cope, you could (with my help as needed) always replicate things using a wee bit of inline assembly...

I suppose I should really download what you've already got so far and give it a quick spin.

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

7. Re: Phix: cffi.e

petelomax said...

I suppose I should really download what you've already got so far and give it a quick spin.

Thank you for the quick reply,

I don't really have anything tangible at the moment. But there's no need to rush either. Programming is just a hobby for me.

unfortunately I'm more than busy enough with my real life at the moment.

But I think at the weekend I'll find the peace and time to put something together that someone can work with.

Thank you

Andreas

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

8. Re: Phix: cffi.e

Hallo,

i just had to try it blink works

I would never have thought of trying it this way. there has been a function in tinlib for over 10 years that has never worked because of this problem (WindowFromPoint).
of course i still have to test if there are any memory leaks.

thanks a lot

Andreas

petelomax said...

Hmm, maybe something like this would work (where color is a single #RRGGBBAA value):

local constant xDrawCircleV = define_c_proc(ray,"+DrawCircleV",{C_FLOAT,C_FLOAT,C_FLOAT,C_DWORD})  
c_proc(xDrawCircleV,{x,y,radius,color}) 

only for windows 32bit but it works

-- file: ray.e  
-- practically everything is shamelessly copied from Icy Vikings raylib.e 
atom ray  
 
constant Color =C_ULONG 
 
public struct Vector2 
    atom x = 0 
    atom y = 0 
end struct 
 
 
 
ray = open_dll("raylib.dll") 
 
if ray = 0 then 
        puts(1,"Unable to load Raylib!\n") 
        abort(0) 
end if 
 
--public function makeRGB(integer REDi,integer GREENi, integer BLUEi,integer ALPHAi) 
--      return(REDi+BLUEi*256+(GREENi*256*256)+(ALPHAi*256*256*256)) 
--end function 
 
public function makeRGB(sequence color) 
        return(color[1]+color[2]*256+(color[3]*256*256)+(color[4]*256*256*256)) 
end function 
 
 
public constant WHITE = {255,255,255,255}, 
                BLACK = {0,0,0,255}, 
                MAGENTA = {255,0,255,255}, 
                RAYWHITE = {245,245,245,255}, 
                RED       = {230,41,55,255}, 
                MAROON    = {190,33,55,255}, 
                GREEN     = {0,228,48,255}, 
                LIME      = {0,158,47,255}, 
                DARKGREEN = {0,117,44,255}, 
                SKYBLUE   = {102,191,255,255}, 
                BLUE      = {0,121,241,255}, 
                YELLOW    = {253,249,9,255} 
 
 
constant xInitWindow = define_c_proc(ray,"+InitWindow",{C_INT,C_INT,C_PTR}), 
        xCloseWindow = define_c_proc(ray,"+CloseWindow",{}), 
  xWindowShouldClose = define_c_func(ray,"+WindowShouldClose",{},C_BOOL), 
       xSetTargetFPS = define_c_proc(ray,"+SetTargetFPS",{C_INT}), 
       xBeginDrawing = define_c_proc(ray,"+BeginDrawing",{}), 
         xEndDrawing = define_c_proc(ray,"+EndDrawing",{}), 
    xClearBackground = define_c_proc(ray,"+ClearBackground",{C_ULONG}), 
           xDrawText = define_c_proc(ray,"+DrawText",{C_PTR,C_INT,C_INT,C_INT,Color}), 
        xDrawCircleV = define_c_proc(ray,"+DrawCircleV",{C_FLOAT,C_FLOAT,C_FLOAT,Color}) 
         
public procedure InitWindow(atom width,atom height,sequence title) 
atom ptitle = allocate_string(title)         
        c_proc(xInitWindow,{width,height,ptitle}) 
        free(ptitle) 
end procedure 
 
public procedure CloseWindow() 
        c_proc(xCloseWindow,{}) 
end procedure 
 
public function WindowShouldClose() 
        return c_func(xWindowShouldClose,{}) 
end function 
 
public procedure SetTargetFPS(atom fps) 
        c_proc(xSetTargetFPS,{fps}) 
end procedure 
 
public procedure ClearBackground(object  color) 
        c_proc(xClearBackground,{makeRGB(color)}) 
end procedure 
 
public procedure BeginDrawing() 
        c_proc(xBeginDrawing,{}) 
end procedure 
 
public procedure EndDrawing() 
        c_proc(xEndDrawing,{}) 
end procedure 
 
public procedure DrawText(sequence text,atom x,atom y,atom fontSize,sequence color) 
atom ptext =allocate_string(text) 
        c_proc(xDrawText,{ptext,x,y,fontSize,makeRGB(color)}) 
        free(ptext) 
end procedure 
 
public procedure DrawCircleV(Vector2 center,atom radius,sequence color) 
        c_proc(xDrawCircleV,{center.x,center.y,radius,makeRGB(color)}) 
end procedure 
--file BasicWin.ex 
include ray.e 
 
constant Width = 800 
constant Height = 600 
 
InitWindow(Width,Height,"Simple Window") 
 
SetTargetFPS(60) 
 
Vector2 pos =new() 
pos.x=Width/2.5 
pos.y=Height/2.5 
 
while not WindowShouldClose() do 
        BeginDrawing() 
        ClearBackground(BLUE) 
        DrawCircleV(pos,100,RED) 
        DrawText("Simple Window Program",Width /2.5, Height /2.5 ,20,YELLOW) 
         
        EndDrawing() 
end while 
 
CloseWindow() 
new topic     » goto parent     » topic index » view message » categorize

9. Re: Phix: cffi.e

andreasWagner said...

only for windows 32bit but it works

They are rare, but I've seen a couple of places where this bites, for instance libcurl.e has this:

 
    if xcurl_easy_setopt=NULL then 
        xcurl_easy_setopt = define_c_func(libcurl, "curl_easy_setopt", {C_PTR, C_INT, C_PTR}, C_INT) 
        if machine_bits()=32 then -- split a curl_off_t (64 bit int) into two 32-bit ints 
            xcurl_easy_setopt2 = define_c_func(libcurl, "curl_easy_setopt", {C_PTR, C_INT, C_PTR, C_PTR}, C_INT) 
        end if 
    end if 
    ... 
    if machine_bits()=32 and option>30000 then 
        atom paramhi = floor(param/#1_0000_0000) 
        param = remainder(param,#1_0000_0000) 
        res = c_func(xcurl_easy_setopt2, {curl, option, param, paramhi}) 
    else 
        res = c_func(xcurl_easy_setopt, {curl, option, param}) 
    end if 

It may be that you need to ram two floats into a 64-bit value the hard way, ie faff about with poke(atom_to_float32()) and peek8(), on 64-bit.

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

10. Re: Phix: cffi.e

petelomax said...
andreasWagner said...

only for windows 32bit but it works

They are rare, but I've seen a couple of places where this bites, for instance libcurl.e has this:

 
    if xcurl_easy_setopt=NULL then 
        xcurl_easy_setopt = define_c_func(libcurl, "curl_easy_setopt", {C_PTR, C_INT, C_PTR}, C_INT) 
        if machine_bits()=32 then -- split a curl_off_t (64 bit int) into two 32-bit ints 
            xcurl_easy_setopt2 = define_c_func(libcurl, "curl_easy_setopt", {C_PTR, C_INT, C_PTR, C_PTR}, C_INT) 
        end if 
    end if 
    ... 
    if machine_bits()=32 and option>30000 then 
        atom paramhi = floor(param/#1_0000_0000) 
        param = remainder(param,#1_0000_0000) 
        res = c_func(xcurl_easy_setopt2, {curl, option, param, paramhi}) 
    else 
        res = c_func(xcurl_easy_setopt, {curl, option, param}) 
    end if 

It may be that you need to ram two floats into a 64-bit value the hard way, ie faff about with poke(atom_to_float32()) and peek8(), on 64-bit.

What I have found so far in raylib, these stumbling blocks are not rare. For 64bit I just gave up for the moment.
The following sentences are from the Phix documentation (define_c_func).

Currently, there is no way to pass a C structure by value or get a C structure as a return result. 
You can only pass a pointer to a structure and get a pointer to a structure as a result.  
I think I'll just wait until these features are possibly included in a Phix 2.0 version.

Until then I'll play around with raylib(phix) here:
https://github.com/andizk4kx/raylib-playground/tree/main

Thanks for your support and especially for Phix.

Andreas

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

Search



Quick Links

User menu

Not signed in.

Misc Menu