r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3 Extensions] REBOL 3 Extensions discussions

Maxim
10-Nov-2010
[1704]
is your file a .c or .cpp  ?
Oldes
10-Nov-2010
[1705]
.c
Maxim
10-Nov-2010
[1706]
you can try adding 

extern  void RL_Print(char *fmt, ...);

at the begining of your file.
Oldes
10-Nov-2010
[1707]
That does not works.
Maxim
10-Nov-2010
[1708x2]
are you using gcc of VS ?
of = or
Oldes
10-Nov-2010
[1710x3]
GCC
it's not working with Andreas' minimal example as well - http://www.curecode.org/rebol3/ticket.rsp?id=1727
(wrong link, this one https://gist.github.com/0c6305d7c25e40742b31
)
Maxim
10-Nov-2010
[1713x2]
ah, I did a little bit of searching and I think I understand... 

try using RL_PRINT() instead.
its strange that I've never had a problem with this though cause 
I use RL_Print in all my files, but I realize that it might just 
be luck, that in my setup I don't have the linking problem you are 
having.
Oldes
10-Nov-2010
[1715]
That works, but only with 2 args.
Maxim
10-Nov-2010
[1716x5]
RL_PRINT should work in any uses of the host_kit
ok... that is easy to fix.
open reb-lib.h
and replace:
#define RL_PRINT(a,b)               RL->print(a,b)

with:
#define RL_PRINT(a,b)               RL->print(a,__VA_ARGS__)

can't test it right now, but that should work.
the function itself is defined with variable arguments, its just 
the #define which isn't ... the above redefines it so it matches 
the function declaration.
Oldes
10-Nov-2010
[1721]
__VA_ARGS__ can only appear in the expansion of a C99 variadic macro
Never mind... I really have to do real work now :)
Maxim
10-Nov-2010
[1722]
what?  I'm using it my own gcc compiled version of the host-kit... 
I don't understand... Andreas will have to step in... I don't know 
why you're having that error.
Oldes
10-Nov-2010
[1723]
Actually it's:

../src/include/reb-lib.h:270:49: warning: __VA_ARGS__ can only appear 
in the expansion of a C99 variadic macro

wand.c:74:43: macro "RL_PRINT" passed 3 arguments, but takes just 
2
wand.c: In function `RX_Call':

wand.c:74: error: `RL_PRINT' undeclared (first use in this function)
Maxim
10-Nov-2010
[1724]
ok, well, I guess you'll have to use just two args for now  ;-)
Oldes
10-Nov-2010
[1725]
But I have a solution, this works:
RL->print("%d %s\n", n,item);
Maxim
10-Nov-2010
[1726x2]
true.


btw, keep reb-lib.h open when you code extension stuff, its the best 
source to get the proper argument information for all the available 
RLxxxxx functions.
if you look at the web version it mangles the argument types, by 
stripping away any pointer use... so it gets really screwed up.
Oldes
10-Nov-2010
[1728]
Extensions are quite additive as I'm getting closer to a real work 
:) I'm sure I will have other questions, but must force myself to 
stop now.
Maxim
10-Nov-2010
[1729]
yes, once you understand that just about everything obeys the same 
basic pattern, it gets quite easy and addictive, since you get results 
pretty quickly  :-)
Oldes
10-Nov-2010
[1730x2]
true, once I will understand the patterns, I will make a script, 
which will create the C code for me.
oh s**t, I cannot stop.. I'm already able to convert images..
Maxim
10-Nov-2010
[1732]
hahaha
Pekr
10-Nov-2010
[1733]
Oldes - LOL :-)
Gregg
11-Nov-2010
[1734]
:-)
Oldes
11-Nov-2010
[1735x3]
When I have integer (from REBOL side) and want to use it as a pointer, 
what I must do?
And, what would you do: (1.) Save wand pointers on REBOL side, or 
(2.) only on C side and provide just IDs (index) to this pointers 
(which is probably safer but would require dynamic array on the C 
side)?
I think I've found answer on my question, but please correct me, 
if there is better way:
            i32 magick_wand_ptr;
            MagickWand *magick_wand;
            
            magick_wand_ptr = RXA_INT32(frm, 1);
            magick_wand = magick_wand_ptr;
Cyphre
11-Nov-2010
[1738]
I think you could just do this:

magick_wand = (MagickWand*)RXA_INT32(frm, 1);
Oldes
11-Nov-2010
[1739x4]
Right, that works as well:)
I§m having problems to get string from REBOL input if it's unicode:/
So with Cyphre's help I have this function:
char* rebser_to_utf8(REBSER* series) {
    char *uf8str;
    REBCHR* str;
    REBINT result = RL_GET_STRING(series, 0 , (void**)&str);
        
    if (result > 0){
        //unicode string
        int iLen = wcslen(str);
        int oLen = iLen *  sizeof(REBCHR);
        uf8str = malloc(oLen);

        int result = WideCharToMultiByte(CP_UTF8, 0, str, iLen, uf8str, oLen, 
        0, 0);
        if (result == 0) {
            int err = GetLastError();
            RL->print("err: %d\n", err);
        }
    } else if (result < 0) {
        //bytes string (ascii or latin-1)
        uf8str = malloc(strlen((char *)str));
        strcpy(uf8str, (char *)str);
    }
    return uf8str;
}

and I can than use:
..
            char *filename = rebser_to_utf8(RXA_SERIES(frm, 1));
            status=MagickReadImage(current_wand, filename);
            free(filename);
            if (status == MagickFalse) {
                ThrowWandException(current_wand);
            }
            return RXR_TRUE;
Is it correct? It's working but maybe there is something I don't 
see as a C newbie.
BrianH
11-Nov-2010
[1743]
Why are you using an integer on the REBOL side to store a pointer? 
That is what handle! is for.
Oldes
11-Nov-2010
[1744]
because I don't know handle. I'm learning and there are no examples 
yet
BrianH
11-Nov-2010
[1745]
REBOL doesn't have pointers, it has references, and it doesn't have 
addresses. So the only way you could legitimately get a pointer is 
to return it from a command. But you don't want to have any way to 
construct an illegitimate pointer in REBOL and pass it to a command 
because that would be a much worse security and stability problem 
than just having commands at all, and treating pointers as integers 
lets you do that. So there is the handle! type to store pointers. 
A handle! is an immediate value that is the size of a pointer, but 
that you can't convert directly to or from any other value, or even 
mold it to see its contents. When you return a pointer from a command 
you set the value to the handle! type. Then that handle! will be 
usable when passed back to other commands in the same extension, 
and maybe even when passed to other extensions, depending on address 
space issues. Handles are also used to store function pointers in 
R3, and other opaque system values like library addresses.
Oldes
11-Nov-2010
[1746]
changed to use handle, but the string conversion function is probably 
bad.
BrianH
11-Nov-2010
[1747]
What you absolutely don't want to have available in REBOL code is 
address arithmetic. That should be reserved for native code.
Oldes
11-Nov-2010
[1748]
Right, now it's clear that I cannot mess with the wand pointers, 
so it's safe to store the wands on the REBOL side. Thanks for that 
info.
BrianH
11-Nov-2010
[1749]
And on that subject, what is the current state of string conversion 
in extensions? When last I checked it was really poor, all sorts 
of missing macros.
PeterWood
11-Nov-2010
[1750]
Oldes: HAve you tested the function with a string including a unicode 
code point which translates to a three-byte utf-8 character? The 
size of utf8str appears to beonly  twice the number of codepoints 
in the REBOL stirng.


A good example of a three-byte utf-8 character is the Euro sign - 
Unicode 20AC UTF-8 E2 82 AC
Oldes
11-Nov-2010
[1751]
Right, so what is the best way to allocate the buffer. Also the function 
as it is is working strange if I use it multiple times. So I guess 
the allocation is bad.
PeterWood
11-Nov-2010
[1752x2]
The maximum length of a utf-8 translation of a UCS-2 string would 
be 1.5 times the length of the string. So if wcslen returns the number 
of codepoints in a string, the length of the utf-8 should be the 
length of the str multiplied by 3 integer divided by 2 plus 1.
If wcslen returns the length in bytes then multiply it by 3.