Yes!! That works:
julia> p = Ref{Ptr{Void}}()
Base.RefValue{Ptr{Void}}(Ptr{Void} @0x0000000000000000)
julia> ccall((:sp_get_port_by_name, "libserialport"),Cint,(Cstring, Ref{Ptr{
Void}}), "/dev/cu.usbmodem1413", p)
0
julia> bytestring(ccall((:sp_get_port_name, "libserialport"), Ptr{Cchar}, (
Ptr{Void},), p[]))
"/dev/cu.usbmodem1413"
julia> bytestring(ccall((:sp_get_port_description, "libserialport"), Ptr{
Cchar}, (Ptr{Void},), p[]))
"STM32 STLink"
and so forth.
Based on your help, I'm now also able to ccall a function with this
signature
enum sp_return sp_list_ports(struct sp_port ***list_ptr);
as folllows:
julia> ports = Ref{Ptr{Ptr{Void}}}()
julia> ccall((:sp_list_ports, "libserialport"), Cint, (Ref{Ptr{Ptr{Void
}}},), ports)
julia> ports
Base.RefValue{Ptr{Ptr{Void}}}(Ptr{Ptr{Void}} @0x00007ffe8d8f2a00)
julia> a = pointer_to_array(ports[], (2,), true)
2-element Array{Ptr{Void},1}:
Ptr{Void} @0x00007ffe8d9617e0
Ptr{Void} @0x00007ffe8d989990
julia> bytestring(ccall((:sp_get_port_name, "libserialport"), Ptr{Cchar}, (
Ptr{Void},), a[1]))
"/dev/cu.Bluetooth-Incoming-Port"
julia> bytestring(ccall((:sp_get_port_name, "libserialport"), Ptr{Cchar}, (
Ptr{Void},), a[2]))
"/dev/cu.usbmodem1413"
Maybe that's useful to others who, like me, find call signatures like this
to be a bit tricky.
Many thanks,
Andrew
On Thursday, February 11, 2016 at 8:35:37 AM UTC-7, Andrew Adare wrote:
>
> I'm trying to call out to some library functions from libserialport
> <http://sigrok.org/wiki/Libserialport>. It is a small c library that
> makes extensive use of opaque structs in the API. In c I can do the
> following:
>
> #include <libserialport.h>
> #include <stdio.h>
>
>
> // Compile:
> // gcc -o example example.c $(pkg-config --cflags --libs libserialport)
>
>
> int main(int argc, char *argv[])
> {
> char *uri = argv[1];
> struct sp_port *port;
>
>
> if (sp_get_port_by_name(uri, &port) == SP_OK)
> {
> char *portname = sp_get_port_name(port);
> char *portdesc = sp_get_port_description(port);
> printf("Port name: %s\n", portname);
> printf("Description: %s\n", portdesc);
> }
> else
> printf("Could not find %s\n", uri);
> return 0;
> }
>
>
> As an example, if I run this with an ARM STM32 microcontroller plugged in
> to my USB port, I get the following correct output (on OS X):
>
> $ ./example /dev/cu.usbmodem1413
> Port name: /dev/cu.usbmodem1413
> Description: STM32 STLink
>
> I want to call sp_get_port_by_name from Julia. It has this signature:
>
> enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **
> port_ptr);
>
> The ccall docs advise declaring an empty type as a placeholder for an
> opaque struct, then passing in a reference to it. I've tried many wrong
> things, such as the following:
>
> julia> type Port end
>
> julia> p = Ref{Port}()
> Base.RefValue{Port}(#undef)
>
> julia> ccall((:sp_get_port_by_name, "libserialport"),Cint,(AbstractString,
> Ref{Ref{Port}}),"/dev/cu.usbmodem1413",p)
> 0
>
> julia> p
> Base.RefValue{Port}(Segmentation fault: 11
>
>
> Any tips? The double pointer is causing me some confusion.
>
> Andrew
>