Exactly. The first argument to ccall is a tuple with a symbol pointing to the function name and a const string pointing either to the full path of the dynamic library or just its "canonical" name, in case it is in the standard path your OS uses to find libraries. I had installed liboauth from Homebrew, so it ended up in a standard OS location and I did not use that step, but mistakenly assumed that was what you were supposed to do for libs in non-standard places. Sorry for that, but I'm glad it worked in the end!
-- João Felipe Santos On Mon, Sep 1, 2014 at 6:10 PM, Randy Zwitch <[email protected]> wrote: > Kevin, adding const in front gave me this error: > > type: ccall: expected Symbol, got Ptr{None} > > while loading In[3], in expression starting on line 3 > > Luckily João, your code finally worked for me! So if I understand this > correctly, the problem was that we were originally passing a Ptr to ccall, > when all I should've been doing is passing a string declared as a constant? > > > > On Monday, September 1, 2014 4:46:07 PM UTC-4, João Felipe Santos wrote: > >> I'm sorry, there was a mistake in my example. The dlopen step should be >> used just to check whether the file is accessible as a shared library. >> ccall expects the full path to the .dylib file in case the library is not >> at a "standard" location. >> >> Do something like this instead: >> >> const liboauth = "/path/to/liboauth" >> (dlopen_e(liboauth) == C_NULL) && error("Unable to load shared >> library at the given path.") >> b64d = ccall((:oauth_sign_hmac_sha1, liboauth), Ptr{Uint8}, >> (Ptr{Uint8}, Ptr{Uint8}), testurl, testkey) >> println(bytestring(b64d)) >> >> Note that you have to use bytestring and not string. string will create a >> string from printing the pointer (which will show something like Ptr{Uint8} >> @0x0000012345). bytestring converts a C string from a pointer to an >> ASCIIString, which is what you want. >> >> -- >> João Felipe Santos >> >> >> On Mon, Sep 1, 2014 at 4:24 PM, Randy Zwitch <[email protected]> >> wrote: >> >>> Thanks for the suggestions everyone. Unfortunately, neither the code >>> from Ivar nor João worked for me. >>> >>> liboauth = dlopen("/usr/local/lib/liboauth.dylib") >>> >>> Out[8]: >>> >>> Ptr{Void} @0x00007fdc665c5ca0 >>> >>> In [9]: >>> >>> function oauth_sign_hmac_sha1(m::String,k::String) >>> >>> res = >>> ccall((:oauth_sign_hmac_sha1,liboauth),Ptr{Uint8},(Ptr{Uint8},Ptr{Uint8}),m,k) >>> >>> if res == C_NULL >>> >>> error("oauth_sign_hmac_sha1 failed") >>> >>> end >>> >>> return string(res) >>> >>> end >>> >>> >>> >>> testurl = >>> "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal" >>> >>> testkey = "kd94hf93k423kf44&pfkkdhi9sl3r4s00" >>> >>> oauth_sign_hmac_sha1(testurl, testkey) >>> >>> type: oauth_sign_hmac_sha1: in ccall: first argument not a pointer or >>> valid constant expression, expected DataType, got Type{(Any...,)} >>> while loading In[9], in expression starting on line 11 >>> >>> in oauth_sign_hmac_sha1 at In[9]:2 >>> >>> >>> >>> >>> testurl = >>> "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal" >>> >>> testkey = "kd94hf93k423kf44&pfkkdhi9sl3r4s00" >>> >>> b64d = ccall((:oauth_sign_hmac_sha1, liboauth), Ptr{Uint8}, (Ptr{Uint8}, >>> Ptr{Uint8}), testurl, testkey) >>> >>> bytestring(b64d) >>> >>> type: anonymous: in ccall: first argument not a pointer or valid constant >>> expression, expected DataType, got Type{(Any...,)} >>> while loading In[10], in expression starting on line 3 >>> >>> in anonymous at no file >>> >>> >>> Does this mean I compiled the library wrong? When I did the 'make' step, >>> after it was complete, I did 'make installcheck' and the 3 tests reported >>> that they completed successfully. >>> >>> At a higher level, I like Isaiah's suggestion of doing this process by >>> hand to really get to understanding what is going on. Is there an eaier >>> external library that one of you could suggest that I could use to walk >>> through the entire process? I've done the examples in the manual using >>> :clock and :getenv and understand what is going on, so now I want to work >>> with a user-installed library to make sure I really get the process. I >>> started with OAuth to see if I could make something usable to work with my >>> Twitter package, but maybe it's not the best starting place. >>> >>> >>> On Monday, September 1, 2014 10:47:22 AM UTC-4, João Felipe Santos wrote: >>> >>>> You need to do ccalls using Ptr{Uint8}. What you can do actually is >>>> wrap the Clang.jl-generated functions with your own functions with an >>>> alternative signature, and then convert from ASCIIString to Ptr{Uint8}. >>>> Note that you probably will need to do it anyways to wrap the return types, >>>> since you probably do not want to work with pointers from Julia :) >>>> >>>> In that specific example, if m and k are ASCIIStrings, conversions will >>>> be done automatically: >>>> >>>> testurl = "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file% >>>> 3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce% >>>> 3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1% >>>> 26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2 >>>> jdk%26oauth_version%3D1.0%26size%3Doriginal" >>>> testkey = "kd94hf93k423kf44&pfkkdhi9sl3r4s00" >>>> b64d = ccall((:oauth_sign_hmac_sha1, liboauth), Ptr{Uint8}, >>>> (Ptr{Uint8}, Ptr{Uint8}), testurl, testkey) >>>> >>>> Note that b64d here will be a Ptr{Uint8}, which you can convert to a >>>> Julia string by using bytestring(b64d). >>>> >>>> -- >>>> João Felipe Santos >>>> >>>> >>>>
