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
>

Reply via email to