World: r3wp
[Red] Red language group
older newer | first last |
Pekr 12-Feb-2012 [4888x2] | I think I understand what you think, but I got lost in translation :-) I will have to think about it few times and try to do some experiments.Thank for putting some time into the topic ... |
I understand the first two steps, but I don't understand, how such a function wrapper in Red/System would look like ... | |
Kaj 12-Feb-2012 [4890x3] | Here's an example from the C library binding: |
on-quit: function [ ; Register handler for normal program termination. ; handler [function! []] ; Callback handler [integer!] return: [logic!] ][ #either OS = 'Syllable [ not as-logic _on-quit handler none none ][ not as-logic _on-quit handler ] ] | |
Instead of passing the handler, you'd execute it directly | |
Pekr 12-Feb-2012 [4893x2] | hmm, as I am not loading the library myself (IIRC R2 had something like addres-of), but Red/System is doing so. I wonder, if there is a way of how actually get the library handle ... |
hmm, I have installed PE Explorer. It can somehow display some DLL related info. In export table, I can see functions entry points. If I understand it correctly, those will be an offsets from address, to which the library is bound after loading? | |
Kaj 12-Feb-2012 [4895x6] | Basically, but that's not the method used when loading manually |
If you can find the functions you need in there, it shouldn't be necessary to load them manually. If so, something else keeps your functions from working | |
If they're not in the list, that would explain why they don't work, because the manual loading is needed to pull them in at run time | |
Besides GetProcAddress, there's a set of a few function for loading libraries and symbols. You'd need to bind them and use them to load the library, which yields the library handle, and then load the functions. They're what load/library and make routine! in REBOL use | |
Not sure if the Windows symbol tables work like I said, so you'll have to try | |
Hm, I'm not sure either if the wrapper function can currently be written like I said. You'd have to use the specific declaration as function! type for the function pointer, but the Red/System type checker may not currently support getting the function pointer in the right type | |
Pekr 12-Feb-2012 [4901] | Hmm, so in my case the situation in Red/System is even worse than possibly in R2 and World, where I could get such a handle from load/library directive, whereas in Red/System, what you describe, is writing completly separate layer. In fact, C's LoadLibrary is not difficult to handle, but still - a C level coding, which I thought is almost eliminated for wrapping purposes ... |
Kaj 12-Feb-2012 [4902x4] | All in all, if it's possible to load the functions manually, it should also be possible to import them at load time with the regular #import method. So something else may be wrong in the binding |
The Red/System situation is certainly not worse: it's the other way around. You can program manual loading with just a few well defined functions, the same that R2 and World use. But normally, you use automatic loading by the operating system, which is the standard and most efficient way to do it, and which R2 and World can't use because they execute bindings at run time | |
It's just that there is no ready binding for manual loading that, so you currently have to program it yourself | |
loading yet | |
Pekr 12-Feb-2012 [4906x2] | This is the code from LEDSet program: bool LoadLedCtrl(void) { g_hLedCtrlInst = LoadLibrary("LedCtrl.dll"); if (!g_hLedCtrlInst) { g_hLedCtrlInst = LoadLibrary("..\\LedCtrl.dll"); return false; } // fpIsPower = (LSN_ISPOWER)GetProcAddress(g_hLedCtrlInst, "LSN_IsPower"); |
So, if I would wrap LoadLibrary and GetProcAddress, I could get what you describe? :-) | |
Kaj 12-Feb-2012 [4908x3] | See, the library handle comes from the standard library loading function (well, Windows standard) |
Yes, that would make your binding work the same way as the C code, so if that doesn't work, you definitely know the problem is elsewhere | |
Can you show your complete #import specification and the definition of a function that doesn't work? | |
Pekr 12-Feb-2012 [4911x2] | #import [ "LedCtrl.dll" cdecl [ led-is-power?: "LSN_IsPower" [ return: [logic!] ] led-open-card: "LSN_OpenCard" [ return: [logic!] ] led-get-screen-number: "LSN_GetLedScrNumb" [ return: [integer!] ] led-set-power: "LSN_Power" [ power-on? [logic!] return: [logic!] ] led-get-brightness: "LSN_GetBright" [ return: [integer!] ] |
led-get-brightness is the first one to fail ... | |
Andreas 12-Feb-2012 [4913] | your lib uses stdcall, so better use stdcall instead of cdecl (though that's most likely not the culprit here) |
Pekr 12-Feb-2012 [4914] | I used that, I changed it later to give it a try ... |
Andreas 12-Feb-2012 [4915x2] | rest looks good to me, at first glance |
just to be sure: in the code example from the LEDSet program you gave earlier, is there maybe some initialisation function called _after_ all the proc addrs have been retrieved? | |
Pekr 12-Feb-2012 [4917x2] | there is plenty of ASSERT(fpIsPower != NULL);, for each funcitons, then function LoadLedCtrl returns true ... |
well, I am bothering you here more, than if I would upload somewhere a project file with all sources. The app is really small, but I might be missing some obvious setting or something else :-) | |
Kaj 12-Feb-2012 [4919] | An initialisation function is indeed a good candidate for the problem |
Pekr 12-Feb-2012 [4920] | http://xidys.com/pekr/ledset-source.zip |
Kaj 12-Feb-2012 [4921] | It's not that obvious, the C code does strange indirections :-) |
Pekr 12-Feb-2012 [4922] | Kaj - so I defined following functions. It returns something :-) Hopefully I have an integer handle, representing the "address"? of the requested function. Now is the last step you described - how should I invoke it? "Kernel32.dll" stdcall [ load-library: "LoadLibraryA" [ name [c-string!] return: [integer!] ] get-proc-address: "GetProcAddress" [ library-handle [integer!] function-name [c-string!] return: [integer!] ] ] print ["load-library: " handle: load-library "LedCtrl.dll" lf] print ["get-proc-address: " get-proc-address handle "LSN_IsPower" lf] |
Kaj 12-Feb-2012 [4923x4] | led-power?: function [ handler [function! [return: [logic!]]] return: [logic!] ][ handler ] |
led-power? as function! get-proc-address handle "LSN_IsPower" | |
Something like that, but I'm not sure the casting to function! type will be accepted | |
get-proc-address should really be defined as return: [function!] but that's not currently supported | |
Pekr 12-Feb-2012 [4927] | *** Compilation Error: invalid definition for function led-power?: [function! [return: [logic!]]] |
Kaj 12-Feb-2012 [4928] | Ah, that's only supported in import functions, I think. That's why I handle them as integers everywhere, but then you can't call it as a function. So game over |
Pekr 12-Feb-2012 [4929x2] | I will return to serial communication decoding, although that's not much fun :-) |
Some Red/System type casting will not help? :-) | |
Kaj 12-Feb-2012 [4931] | No, because those casts aren't supported yet |
Pekr 12-Feb-2012 [4932] | Anyway - it was a good way to learn a few bits in a practical manner :-) |
Kaj 12-Feb-2012 [4933] | I can't find anything in the C++ code, though, that would necessitate manual loading. It looks like the regular #import should work. What errors are you getting exactly from those functions? |
Pekr 12-Feb-2012 [4934] | *** Runtime Error 99: unknown error *** at: 7572FC56h |
Kaj 12-Feb-2012 [4935] | Doc may need to have a look at it |
Pekr 12-Feb-2012 [4936] | R2 and World crash. In fact I think that those functions just try to write to serial port ... |
Kaj 12-Feb-2012 [4937] | If R2 and World crash the same way, manual loading doesn't help |
older newer | first last |