World: r3wp
[!REBOL3 Extensions] REBOL 3 Extensions discussions
older newer | first last |
Maxim 11-Nov-2010 [1765x3] | Oldes, thanks for that UTF-8 function converter :-) |
we can return RXR_ERROR, but I don't think it really generates errors... though I haven't even tested it at length. | |
what you can do, is wrap your command within a function in the extension's module and expose that function. this allows you to control the return type of the command better and handle it within the comfort of rebol. | |
Oldes 12-Nov-2010 [1768] | Again with Cyphre's help, here is a function which converts MultiByte (utf-8) string from C side to REBSER used to return the string to REBOL side: REBSER* MultiByteToRebser(char* mbStr) { int len = MultiByteToWideChar( CP_UTF8, 0, mbStr, -1, NULL, 0); //the len is length of the string + null terminator wchar_t *wcStr = malloc(len * sizeof(wchar_t)); int result = MultiByteToWideChar(CP_UTF8, 0, mbStr, strlen(mbStr), wcStr, len); if (result == 0) { int err = GetLastError(); RL->print("ERROR: MultiByteToWideChar -> %d\n", err); exit(-1); //how to throw ERROR on REBOL side? } REBSER *ser = RL_MAKE_STRING(len-1,TRUE); REBUNI *dst; //hack! - will set the tail to len REBINT *s = (REBINT*)ser; s[1] = len-1; RL_GET_STRING(ser,0,(void**)&dst); wcscpy(dst, wcStr); free(wcStr); wcStr = NULL; return ser; } I'm not sure how safe it is, but it seems to be working. To return the string value I use: RXA_TYPE(frm, 1) = RXT_STRING; RXA_SERIES(frm, 1) = (REBSER *)MultiByteToRebser(utf8str); return RXR_VALUE; |
Cyphre 13-Nov-2010 [1769] | This looks ok Oldes. But be aware of the 'hack' part . I put it there just to show you it is possible to copy the whole string without using loop with RL_SET_CHAR. In case Carl changes the REBSER internal struct this function will stop work. But I think you are safe to use the 'hack' at the moment until Carl enhance the HostKit api. One small note in general. Always put all variable declaration at the beginning of code block in C as some compilers will complain about it. |
jocko 13-Nov-2010 [1770] | Updated my ImageMagick extension and doc. It is now possible to exchange image data between Rebol and ImageMagick without using disk files, thanks to the "mpr:" (memory program register) format which allows in-memory save and recover. http://www.colineau.fr/rebol/R3_extensions.html(refresh the page in your web navigator) |
jocko 14-Nov-2010 [1771] | I have put also the sources (Visual Studio project) |
Oldes 30-Nov-2010 [1772x3] | I have a minute again.. so next step in my lesson... Lets have: typedef enum { UndefinedResolution, PixelsPerInchResolution, PixelsPerCentimeterResolution } ResolutionType; and function like: SomeFunc(const ResolutionType units); What's the best way how to provide the units from the REBOL side to the extension's command? |
I know I can use integers instead of the names, or constant variables with integers on the REBOL side but isn't there some other, better way? | |
Providing integers from REBOL side is pretty unstable solution, so I guess I should use words somehow. | |
ChristianE 30-Nov-2010 [1775x2] | Not sure If that's what you're after, but anyways ... ---- REBOL side ---- convert: command [value [number!] unit [word!]] ---- C side ---- if (unit == RL_MAP_WORD("ppi")) { // do something } elseif (unit == RL_MAP_WORD("ppcm")) { // do some other thing } Do you get the idea? >> convert 18 'ppi >> convert 20 'ppcm |
Happily ignoring your ENUM, but hey, who cares? ;-) | |
Oldes 30-Nov-2010 [1777x2] | That's too complex as on my C side I would like to have just the one function. Some enums can be pretty large. |
on the other side I could just do range test and use the integer/variable from REBOL side. | |
ChristianE 30-Nov-2010 [1779] | Would that work? Is it even proper C? typedef enum { PixelsPerInchResolution = RL_MAP_WORD("ppi"), PixelsPerCentimeterResolution = RL_MAP_WORD("ppcm"), ... } |
Oldes 30-Nov-2010 [1780] | I don't think so. |
ChristianE 30-Nov-2010 [1781x2] | Why do you think the first idea is too complex? I for now don't get the "I would like to have just one function" argument. |
How would one function be more simple using only enums? | |
Oldes 30-Nov-2010 [1783x2] | if (unit == RL_MAP_WORD("PixelsPerInchResolution")) { SomeFunc(PixelsPerInchResolution); } elseif (unit == RL_MAP_WORD("PixelsPerCentimeterResolution")) { SomeFunc(PixelsPerCentimeterResolution); } else { SomeFunc(UndefinedResolution); } it just looks strange. |
Also this is simplified case, what if I would have more enum args? | |
ChristianE 30-Nov-2010 [1785] | No, I didn't mean to dispatch to different functions, it's meant as an if/else statement in SomeFunc. |
Oldes 30-Nov-2010 [1786] | Ah.. yes.. that would be fine, but I would like to write wrapper to existing functions, not to write the functions. |
ChristianE 30-Nov-2010 [1787x4] | I was about to suggest RXIEXT int SomeFunc(RXIFRM *frm) { int unit = RL_GET_VALUE(frm, 0, RXT_WORD); if (unit == RL_MAP_WORD("PixelsPerInchResolution")) { } elseif (unit == RL_MAP_WORD("PixelsPerCentimeterResolution")) { } else { } } |
Than you mentioned the wrapper you're going to write. Let me think about that a bit. | |
*Than = Then | |
So, no creative solutions from me, then, I guess. | |
Oldes 30-Nov-2010 [1791x2] | I have this one so far: int unit = RXA_INT64(frm, 1); if(unit >= 0 && unit < 3) { SomeFunc(unit); return RXR_TRUE; } return RXR_FALSE; and in REBOL just: SomeFunc 2 or PixelsPerCentimeterResolution: 2 SomeFunc PixelsPerCentimeterResolution or using dialect |
I guess there is no easy solution as the enum is converted to the integer during compilation. If we are only in C. | |
ChristianE 30-Nov-2010 [1793x3] | How is the above superior to ---- REBOL ---- some-func 'pixels-per-centimeter-resolution ---- C ---- if (unit == RL_MAP_WORD("pixels-per-centimeter-resolution") { SomeFunc(unit); return RXR_TRUE; } But a dialected approach like >> some-func: func [unit [word!]] [select [pixels-per-inch-resolution 1 pixels-per-centimeter-resolution 2] unit] does look ok to me, though. At least, that way, assigning other numerical values to the "keywords" wouldn't harm. |
Probably easier to maintain in REBOL than in C. | |
(Typo in the above, should've read "SomeFunc(2)" instead of "SomeFunc(unit)", but that has already been replaced by the REBOL dialect anymways) | |
Oldes 30-Nov-2010 [1796x2] | the problem with the above is, that in A110: words: [pixels-per-centimeter-resolution] export testword: command ['wrd [lit-word!]] ... case testword: { int unit = RL_MAP_WORD("pixels-per-centimeter-resolution"); RL->print("int: %d\n", unit); } prints int: 1399 = something what I don't expect :) |
for: int unit = RXA_WORD(frm, 1); I get 1381 | |
ChristianE 30-Nov-2010 [1798x2] | That is expected ;-) The numbers you'll get are fairly random. You would have to get the word-number of a supplied word and compare it to the word-number of the allowed words. If they match, act accordingly. |
Or, as stated, compare words in REBOL, e.g. as in my SELECT example. But just don't rely on PIXELSPERCENTIMETERRESOLUTION: 2 | |
Oldes 30-Nov-2010 [1800x2] | now I see that in host-graphics.c is used something like: u32 w = RL_FIND_WORD(graphics_ext_words,RXA_WORD(frm, 1)); switch(w) { case W_GRAPHICS_SCREEN_SIZE: x = GetSystemMetrics(SM_CXSCREEN); y = GetSystemMetrics(SM_CYSCREEN); break; case W_GRAPHICS_TITLE_SIZE: x = 0; y = GetSystemMetrics(SM_CYCAPTION); break; ... |
with: case CMD_GRAPHICS_INIT_WORDS: //temp hack - will be removed later graphics_ext_words = RL_MAP_WORDS(RXA_SERIES(frm,1)); break; | |
ChristianE 30-Nov-2010 [1802] | I never got RL_FIND_WORD to work, but I stopped trying around A102 I guess and forgotten about it since then. |
Oldes 30-Nov-2010 [1803] | (never mind, time to sleep for a while:) |
ChristianE 30-Nov-2010 [1804] | Yeah, time for bed here too, good night. |
Oldes 1-Dec-2010 [1805x5] | hm.. I think I understand how it's supposed to work now, but it looks it's just a temp solution. Here is the init part for graphics: words: [ ;gui-metric screen-size border-size border-fixed title-size work-origin work-size ] ;temp hack - will be removed later init-words: command [ words [block!] ] init-words words |
But I think that the easiest way is to define the enum constants during the extension init like: export PIXELS-PER-INCH-RESOLUTION: 1 export PIXELS-PER-CENTIMETER-RESOLUTION: 2 protect/words [ PIXELS-PER-INCH-RESOLUTION PIXELS-PER-CENTIMETER-RESOLUTION ] and then just use: SomeFunc PIXELS-PER-CENTIMETER-RESOLUTION or SomeFunc 1 with the correct int bound check in the command so only valid numbers are processed. I really like what is possible with R3.. I should start real coding in it soon. | |
Hm.. maybe it's too soon.. the protect seems to be not working if used in the extension's init. I can change the values:/ | |
CC: http://curecode.org/rebol3/ticket.rsp?id=1786 | |
hm.. the protect above is not required anyway as long as there is the validity check in the command. | |
ChristianE 1-Dec-2010 [1810] | Here's how I explained to myself how things went: With A102, the time I started playing around with extensions, there was this RL_FIND_WORD which is supposed to map words against an "extension local" word block. But sadly, I never got that working. It was the "temp hack" comment from which I concluded that the preferred method then became RL_MAP_WORD, which maps a word to a global word id, hence the 1381 number you've got yesterday. With that, you don't need to ENUM in your code but can just compare words supplied with words known. But, I may be totally off track with that reasoning ... wouldn't take me any wonder :-) |
Cyphre 1-Dec-2010 [1811] | Guys, I put the comment about 'temp hack' couple of months ago when I discussed this issue with Carl. Not sure but the init-words trick will probably stay as is because it works fine that way. Ofcourse I may be wrong if there is some better method and Carl decides differently. |
ChristianE 2-Dec-2010 [1812] | Ah, good, to know. So I'm off track indeed, I was expecting that. |
Oldes 5-Dec-2010 [1813] | When I have: #if defined(_WIN64) # define ssize_t __int64 #else # define ssize_t long #endif and function which arg is ssize_t type, how I should get the right value from REBOL in command? Is this correct?: (ssize_t)RXA_INT64(frm, 1)) |
Andreas 5-Dec-2010 [1814] | Yes, Oldes. |
older newer | first last |