I had tried using this before, but incorrectly, I guess. Now this works for
me
# returns names for collections in event
function getCollectionNameArray(event::Ptr{Void})
nameArray = String[]
names = ccall((:lcevtgetcollectionnames, libName), Ptr{Ptr{Uint8}},
(Ptr{Void},), event)
nNames = ccall((:lcevtgetcollectionnamecount, libName), Cint, (Ptr{Void},),
event)
for n in 1:nNames
push!(nameArray, bytestring(unsafe_load(names, n)))
end
ccall(:free, Void, (Ptr{Ptr{Uint8}},), names)
return nameArray
end
getcollectionnamecount is just a call to vector<string>::size() on the c
side.
Not that speed matters in my application, but this is about twice faster
than calling out to vector<string>::at(i) on the C side for every element
individually.
Also, it's just prettier, and my mind can stop feeling dirty now. I might
play with returning the size also in the same call, by passing a Ref{Cint},
but that's for another day.
Thank you very much for your help.
On Sunday, June 14, 2015 at 10:10:00 PM UTC+9, Yichao Yu wrote:
>
>
>
> On Sun, Jun 14, 2015 at 9:00 AM, Jan Strube <[email protected]
> <javascript:>> wrote:
>
>> Thank you for your suggestions.
>> I haven't tried Cxx.jl, since that apparently requires some effort
>> installing a new LLVM, which makes it harder to convince others to use the
>> bindings.
>> Your second suggestion is unfortunately going in the wrong direction,
>> taking a Julia array and passing it to C. It may be obvious to everybody
>> else, but if the C code returns a Ptr{Ptr{Uint8}}, how can I convert this
>> to an Array{String} on the Julia side?
>>
>
> That part is just about how to declare types for ccall. After you've got a
> char**, you can just do the same you do in C to access them.
> In julia, this is done with `unsafe_load`[3]
>
> [3]
> http://julia.readthedocs.org/en/latest/stdlib/c/?highlight=unsafe_load#Base.unsafe_load
>
>
>> I read the manual back and forth, and I understand how to convert a
>> Ptr{Uint8} to a String, using bytestring, but the extension to an Array
>> eludes me.
>>
>>
>>
>>
>> On Sunday, June 14, 2015 at 9:42:46 PM UTC+9, Yichao Yu wrote:
>>
>>>
>>>
>>> On Sun, Jun 14, 2015 at 2:04 AM, Jan Strube <[email protected]> wrote:
>>>
>>>> PPS: Sorry, the segfault actually is unrelated. Nevertheless, I can't
>>>> figure out the right ccall signature.
>>>>
>>>
>>> If you are on a new enough version, you can probably try Cxx.jl[1]
>>> Otherwise, you probably need to do the conversion yourself. Have you
>>> tried `Ptr{Ptr{Cchar}}`?[1]
>>>
>>> [1] https://github.com/Keno/Cxx.jl
>>> [2]
>>> http://julia.readthedocs.org/en/latest/manual/calling-c-and-fortran-code/?highlight=char**
>>>
>>>
>>>>
>>>>
>>>> On Sunday, June 14, 2015 at 2:56:34 PM UTC+9, Jan Strube wrote:
>>>>>
>>>>> PS: My current attempt to return a char** from the vector<string>
>>>>> looks like this:
>>>>> I'm converting to a vector<const char*>, then returning the address of
>>>>> the first element.
>>>>>
>>>>> const char* convert(const std::string& s)
>>>>> {
>>>>> return s.c_str();
>>>>> }
>>>>>
>>>>> const char** lcevtgetcollectionnames( void* event ){
>>>>> LCEventImpl* evt = static_cast<LCEventImpl*>(event);
>>>>> const std::vector<std::string>* nameVec = evt->getCollectionNames();
>>>>> std::vector<const char*>* names = new std::vector<const char*>;
>>>>> std::transform(nameVec->begin(), nameVec->end(),
>>>>> std::back_inserter(*names), convert);
>>>>> return &(*names)[0];
>>>>> }
>>>>>
>>>>>
>>>>> On the Julia side I'm trying this signature:
>>>>> ccall((:lcevtgetcollectionnames, "test.dylib"), Ptr{Cstring},
>>>>> (Ptr{Void},), event)
>>>>>
>>>>> But this results in a seg fault
>>>>>
>>>>> signal (11): Segmentation fault: 11
>>>>>
>>>>> lcevtgetcollectionnames at /Users/stru821/Workdir/Julia/test.dylib
>>>>> (unknown line)
>>>>>
>>>>> anonymous at no file:7
>>>>>
>>>>> jl_apply at
>>>>> /Users/vagrant/buildbot/slave/package_osx10_9/build/src/./julia.h:1299
>>>>>
>>>>> jl_parse_eval_all at
>>>>> /Users/vagrant/buildbot/slave/package_osx10_9/build/src/toplevel.c:573
>>>>>
>>>>> jl_load at
>>>>> /Users/vagrant/buildbot/slave/package_osx10_9/build/src/toplevel.c:616
>>>>>
>>>>> include at
>>>>> /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/lib/julia/sys.dylib
>>>>>
>>>>> (unknown line)
>>>>>
>>>>> jl_apply at
>>>>> /Users/vagrant/buildbot/slave/package_osx10_9/build/src/./julia.h:1299
>>>>>
>>>>> include_from_node1 at loading.jl:133
>>>>>
>>>>> jl_apply at
>>>>> /Users/vagrant/buildbot/slave/package_osx10_9/build/src/gf.c:1632
>>>>>
>>>>> process_options at
>>>>> /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/lib/julia/sys.dylib
>>>>>
>>>>> (unknown line)
>>>>>
>>>>> _start at
>>>>> /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/lib/julia/sys.dylib
>>>>>
>>>>> (unknown line)
>>>>>
>>>>> jlcall__start_18703 at
>>>>> /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/lib/julia/sys.dylib
>>>>>
>>>>> (unknown line)
>>>>>
>>>>> jl_apply at
>>>>> /Users/vagrant/buildbot/slave/package_osx10_9/build/src/./julia.h:1299
>>>>>
>>>>> true_main at
>>>>> /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/bin/julia
>>>>>
>>>>> (unknown line)
>>>>>
>>>>> main at
>>>>> /Applications/Julia-0.4.0-dev-539c818c4e.app/Contents/Resources/julia/bin/julia
>>>>>
>>>>> (unknown line)
>>>>>
>>>>> Segmentation fault: 11
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Sunday, June 14, 2015 at 2:43:24 PM UTC+9, Jan Strube wrote:
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I'm trying to wrap the LCIO file format http://lcio.desy.de/ in
>>>>>> Julia.
>>>>>> I have a proof of principle working and am starting to add more of
>>>>>> the API.
>>>>>>
>>>>>> What totally stumps me is this signature:
>>>>>> virtual const std::vector< std::string > *
>>>>>> getCollectionNames
>>>>>> <http://lcio.desy.de/v02-04-03/doc/doxygen_api/html/classEVENT_1_1LCEvent.html#a9128a3f65b8a94629c0cf5e77c0194ac>
>>>>>> ()
>>>>>> const =0
>>>>>>
>>>>>> http://lcio.desy.de/v02-04-03/doc/doxygen_api/html/classEVENT_1_1LCEvent.html#a9128a3f65b8a94629c0cf5e77c0194ac
>>>>>>
>>>>>> I've created a C library to call from Julia, so I'm happy to convert
>>>>>> the return type to char**, but I just cannot figure out how to write a
>>>>>> ccall that doesn't segfault.
>>>>>> I've seen various examples how to convert a Julia array of strings to
>>>>>> a char**, but couldn't find anything that converts a char** to Julia
>>>>>> types.
>>>>>>
>>>>>> Any help is greatly appreciated.
>>>>>>
>>>>>> Jan
>>>>>>
>>>>>>
>>>
>