Administrator
|
The ESUG presentation this year was very comprehensive. I suggest making the slides and sample code more prominent/easily accessible from the code.
Using the presentation, I tried to communicate with the portaudio lib (OSX 10.8.5, lib installed with brew). I did: PaInitialize <primitive: #primitiveNativeCall module: #NativeBoostPlugin> ^ self nbCall: #(int _Pa_Initialize()) module: 'libportaudio.dylib' The docs list the function name without the underscore, but nm revealed it with a leading underscore. For the module, I tried: - full path to dylib link above - fill path to actual versioned dylib file i.e. ...2.dylib - symlinking both into the VM Plugins folder I was thinking maybe this was the indirect function thing like chipmunk, but even "self nbGetExtenalAddress: 'Pa_Initialize' module: 'libportaudio.dylib' returned nil. I tried with and without the underscore, with the module specified all four ways. Thanks in advance for any guidance...
Cheers,
Sean |
Administrator
|
Bump. btw I should mention that the error was "function unavailable"
Cheers,
Sean |
On 12 November 2013 02:43, Sean P. DeNigris <[hidden email]> wrote: Sean P. DeNigris wrote sorry, i was out on weekend.. first thing to do is to: file youlib.dylib and check it is 32-bit compatible. and second is nbGetSymbolAddress: aName module: aModuleNameOrHandle you can also try to use #ioLoadModule: method to check if library can be loaded. with mangled symbols things are a bit tricky.. sometimes it extra underscore.. sometimes even two of them.. on mac, use otool to figure exported symbols.
-- Best regards, Igor Stasenko. |
Administrator
|
You're not allowed to have a life. You're too important ;) Great! That was the first problem - 64bit only. Recompiled as universal and I'm able to communicate with the lib This is a good trick to know because by going to #nbGetSymbolAddress:module: right away, one can't tell whether it's the library or the symbol can't be found. This narrows it down. The weird thing is that "nm -g" showed the function with a leading underscore, "otool -TV" showed no exported symbols, and from NB, what actually worked was the function name without any leading underscore. Anyway, I'm implementing one of the demos. I'll let you know how it turns out. Thank you for the support!!!
Cheers,
Sean |
Administrator
|
Okay, I got a little further. I can initialize and terminate the library. Yahoo!! To load the very basic spike: Gofer it smalltalkhubUser: 'SeanDeNigris' project: 'PortAudio'; package: 'PortAudio'; load. My next task is to call... PaError Pa_OpenDefaultStream(PaStream ** stream, "PaStream is typedef for void" int numInputChannels, int numOutputChannels, ulong sampleFormat, double sampleRate, ulong framesPerBuffer, PaStreamCallback streamCallback, void * userData) (see http://portaudio.com/docs/v19-doxydocs/open_default_stream.html) The first argument is most perplexing to me. I haven't seen any NativeBoost examples of pointers to pointers. In fact, with pointers to values, it seems random whether they are derefenced when described in NB. For example: cairo_t* cairo_create (cairo_surface_t *target); becomes (from the IWST paper): self nbCall: #( AthensCairoCanvas cairo_create ( AthensCairoSurface cairoSurface)) Notice the argument is dereferenced in the NB version. But (also from the IWST paper): "void cairo_matrix_multiply ( cairo_matrix_t *result, const cairo_matrix_t *a, const cairo_matrix_t *b );" becomes: self nbCall: #(void cairo_matrix_multiply (AthensCairoMatrix * self, AthensCairoMatrix * m , AthensCairoMatrix * self ) ) In this case, none of the arguments are defererenced. Anyway, I'd reeeeeally appreciate it if someone would load the code and see what the problem is. "PortAudio example" will run the demo script I'm translating from the library docs into Pharo. Thanks in advance...
Cheers,
Sean |
According to its manual (http://portaudio.com/docs/v19-doxydocs/portaudio_8h.html#a0a12735ac191200f696a43b87667b714) stream The address of a PaStream pointer which will receive a pointer to the newly opened stream. So, what you need to pass is a pointer to location where pointer will be stored.
The simplest way how to do it (without explaining you how to use NBExternalValue) just do a following: PaError Pa_OpenDefaultStream(NBExternalAddress * stream ... ) then your call site will look like following: streamHandle := NBExternalAddress new. self Pa_opendefaultBlah: streamHandle ... The 'NBExternalAddress *' type treated specially, because usually for most cases if you pass an instance of NBExternalAddress to any function which expects some pointer, NB will pass the value of NBExternalAddress, however if type is NBExternalAddress * , then NB will pass a pointer where pointer value is stored (which effectively means pointer to pointer) that should do the trick. But hold on, next thing you will stuck with is callback ... hehe :) ah.. ok, according to manual, you can simply skip this one by passing NULL (nil) for that, again you can just change the function signature and instead of putting
put nil. (yes, nil literal) On 13 November 2013 06:11, Sean P. DeNigris <[hidden email]> wrote: Sean P. DeNigris wrote -- Best regards, Igor Stasenko. |
Administrator
|
Okay, one step closer. I somewhat randomly guessed to use NBExternalAddress, but didn't have the correct thing in the signature... So you're saying the signature would become: nbCall: #(PaError Pa_OpenDefaultStream(NBExternalAddress * stream, ... ulong framesPerBuffer, nil, void * userData)) I made the changes as I understood them, but I'm getting a "generic failure" when I call Pa_OpenDefaultStream. I uploaded the latest changes to the repo...
Cheers,
Sean |
Administrator
|
Ping ;) I'm stuck...
Cheers,
Sean |
Administrator
|
Perhaps Igor prefers "bump"... ;)
Cheers,
Sean |
In reply to this post by Sean P. DeNigris
sean
could you propose something for it: adding a class ReadMe? DocuMe? Adding it to the help? Stef On Nov 9, 2013, at 8:21 PM, Sean P. DeNigris <[hidden email]> wrote: > The ESUG presentation this year was very comprehensive. I suggest making the > slides and sample code more prominent/easily accessible from the code. > > Using the presentation, I tried to communicate with the portaudio lib (OSX > 10.8.5, lib installed with brew). > > I did: > PaInitialize > <primitive: #primitiveNativeCall module: #NativeBoostPlugin> > ^ self > nbCall: #(int _Pa_Initialize()) > module: 'libportaudio.dylib' > > The docs list the function name without the underscore, but nm revealed it > with a leading underscore. > > For the module, I tried: > - full path to dylib link above > - fill path to actual versioned dylib file i.e. ...2.dylib > - symlinking both into the VM Plugins folder > > I was thinking maybe this was the indirect function thing like chipmunk, but > even "self nbGetExtenalAddress: 'Pa_Initialize' module: 'libportaudio.dylib' > returned nil. I tried with and without the underscore, with the module > specified all four ways. > > Thanks in advance for any guidance... > > > > ----- > Cheers, > Sean > -- > View this message in context: http://forum.world.st/NativeBoost-Documentation-Suggestion-and-Question-tp4720805.html > Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com. > |
In reply to this post by Sean P. DeNigris
On 13 November 2013 18:08, Sean P. DeNigris <[hidden email]> wrote: Igor Stasenko wrote sorry for late reply. hmm.. everything should work. except i think nil -> void * is not accepted by default. you should use #optCoerceNilToNull option: self nbCall: ... options: #(+ optCoerceNilToNull) or, if you don't wanna mess with options, you can always pass a null pointer by constructing it, a simplest way is to pass dumb and stupid NBExternalAddress null.
-- Best regards, Igor Stasenko. |
On 21 November 2013 16:23, Igor Stasenko <[hidden email]> wrote:
... or since i doubt you will ever use userData argument, best option would be to just change the signature and put nil in it, eliminating need to care about passing and converting useless null parameter(s).
-- Best regards, Igor Stasenko. |
Administrator
|
In reply to this post by Igor Stasenko
Yes! That worked :) Thank you!! Why is that disabled by default? It seems like a fairly common operation...
Cheers,
Sean |
Administrator
|
In reply to this post by Stéphane Ducasse
I'll organize my observations. A few that stood out: - In signature - you must type "ulong", not "unsigned long" - when passing objects as arguments, don't need "*" unless you might pass null - typedefs: declare in shared pool - Pass a pointer receiving external object as an argument: NBExternalAddress new - Pass nil as a pointer argument: NBExternalAddress null
Cheers,
Sean |
In reply to this post by Sean P. DeNigris
On 21 November 2013 17:34, Sean P. DeNigris <[hidden email]> wrote: Igor Stasenko wrote mm.. well, i prefer that fairly common would be to pass meaningful data back and forth rather than dummy values. For that best solution, IMO, would be to use 2 methods which call same function, but one uses 'nil' in function signature (and therefore method doesn't takes extra argument), while other takes extra argument but doesn't accepts nils, for sure.
-- Best regards, Igor Stasenko. |
Administrator
|
> mm.. well, i prefer that fairly common would be to pass meaningful data back and forth rather than
> dummy values. I don't understand... when I say "fairly common", I mean that in the C world, it seems common to use null-passing for optional arguments. I'm not saying that it's a good idea, but we don't have control over that, so... > For that best solution, IMO, would be to use 2 methods which call same function, > but one uses 'nil' in function signature (and therefore method doesn't takes extra argument), > while other takes extra argument but doesn't accepts nils, for sure. Yuck ;)
Cheers,
Sean |
On 21 November 2013 19:10, Sean P. DeNigris <[hidden email]> wrote:
if it would be just C world :) Another reason for not making this default, because checking for nil is one extra check for every piece of generated code which expects pointer, and i hope you agree that while null-value is fairly common, non-null is much more common.
but this is quite common in smalltalk isn't? Look at Canvas - good example of overusing it i.e.: drawThis: withThis: andThat: drawThis: withThis: andThat: andAlsoThis: drawThis: withThis: andThat: andAlsoThis: andAlsoThat: :) yes, sometimes it looks like unnecessary protocol bloating, but i think for our case it is well justified.
-- Best regards, Igor Stasenko. |
Free forum by Nabble | Edit this page |