dyncall               package:rdyncall               R Documentation

_F_o_r_e_i_g_n _F_u_n_c_t_i_o_n _I_n_t_e_r_f_a_c_e _t_o _c_o_m_p_i_l_e_d _c_o_d_e _w_i_t_h _s_u_p_p_o_r_t _f_o_r _m_u_l_t_i_p_l_e _c_a_l_l_i_n_g _c_o_n_v_e_n_t_i_o_n_s.

_D_e_s_c_r_i_p_t_i_o_n:

     Functions to make calls to compiled code with support for multiple
     calling conventions.

_U_s_a_g_e:

     .dyncall( address, signature, ... , callmode = c("cdecl","stdcall") )

     .dyncall.cdecl        ( address, signature, ... )
     .dyncall.stdcall      ( address, signature, ... )

_A_r_g_u_m_e_n_t_s:

 address: An external pointer to a foreign function.

signature: A character string specifying the argument and return type
          of a function call.

callmode: A character string specifying the calling convention.

     ...: Any arguments to be passed via dyncall according to the
          argument types specified in 'signature'.

_D_e_t_a_i_l_s:

     A valid 'address' to a foreign function can be obtained from
     functions such as '.dynfind' and 'getNativeSymbolInfo'.

_V_a_l_u_e:

     The return value of the foreign function call converted to an R
     type according to the return type character given by 'signature'.

_t_e_s_t:

     The 'signature' is a character string that encodes the arity
     (number of arguments)  and formal argument- and return-types using
     a character-based type code.

     The calling convention is specified explicitly by the 'callmode'
     argument  using '.dyncall' or implicitly by using '.dyncall.*'
     functions. 

     The arguments given with '...' are passed and possibly converted
     according to  the given signature.

_S_i_g_n_a_t_u_r_e:

     The general form of a dyncall signature string is

       _Argument types_  ')'  _Return type_

     A type is specified using a one-character type code. The argument
     type characters are specified  in left-to-right order of the
     corresponding C function prototype.  A closing bracket character
     '')'' marks the end of input argument types. Finally, a return
     type character is given to specify the return value.  The
     following table lists valid type character codes, corresponding C
     types, acceptable R argument types and returned R types.

       *Type code*  *C type*            *R argument type*              *R return type*
           'B'      bool                raw,logical,integer,double     logical
           'c'      char                raw,logical,integer,double     integer
           'C'      unsigned char       raw,logical,integer,double     integer
           's'      short               raw,logical,integer,double     integer
           'S'      unsigned short      raw,logical,integer,double     integer
           'i'      int                 raw,logical,integer,double     integer
           'I'      unsigned int        raw,logical,integer,double     double
           'j'      long                raw,logical,integer,double     double
           'J'      unsigned long       raw,logical,integer,double     double
           'l'      long long           raw,logical,integer,double     double
           'L'      unsigned long long  raw,logical,integer,double     double
           'f'      float               raw,logical,integer,double     double
           'd'      double              raw,logical,integer,double     double
           'p'      _type_* (pointer)   _any vector_,externalptr,NULL  externalptr,NULL
           'S'      char*               character,NULL                 character,NULL
           'x'      SEXP                _any_                          _any_
           'v'      void                _invalid_                      NULL

     Some examples of C function prototypes and corresponding function
     type signatures:

       'double sqrt(double);'                     '"d)d"'
       'double dnorm(double,double,double,int);'  '"dddi)d"'
       'void   R_isort(int*,int);'                '"pi)v"'
       'char   foo(int,double,float,bool);'       '"idfB)c"'
       'void   revsort(double*,int*,int);'        '"ppi)v"'

_H_o_w-_t_o _c_o_n_n_e_c_t _t_o _a _l_i_b_r_a_r_y:


        *  Install library. 

        *  Review documentation and headers related to calling
           conventions, constants and function types. 

        *  Test library functions on x86.  

        *  Write a dynport file. 

_C_a_l_l_i_n_g _c_o_n_v_e_n_t_i_o_n_s:

     Calling conventions specify exact low-level information how a
     function call is invoked. The conventions differ heavily from CPU
     type to CPU type. Some conventions are related to OS and Compiler
     issues. While on many processor architectures, there is only one
     general calling convention - there is choice on x86 processor
     architectures and in particular when working with Microsoft
     Windows system libraries.

     In general, many prebuilt binaries available online will work fine
     with '"cdecl"'. 


     '"_c_d_e_c_l"' Default C calling convention. 

     '"_s_t_d_c_a_l_l"' Available on the X86 architecture, otherwise falls
          back to "cdecl". Use when linking Microsoft Windows System
          Libraries (e.g. KERNEL32.DLL, USER32.DLL, OPENGL32.DLL ...). 

     '"_t_h_i_s_c_a_l_l._g_c_c"' Available on the X86 architecture, otherwise
          falls back to "cdecl". Use when calling C++ member functions
          that are linking x86 C++ shared libraries compiled with GCC
          using '__thiscall'.

     '"_t_h_i_s_c_a_l_l._m_s_v_c"' Available on the X86 architecture, otherwise
          falls back to "cdecl". Use when linking x86 shared libraries
          compiled with Visual C++ using '__thiscall'. 

     '"_f_a_s_t_c_a_l_l._m_s_v_c"' Available on the X86 architecture, otherwise
          falls back to "cdecl". 

     '"_f_a_s_t_c_a_l_l._g_c_c"' Available on the X86 architecture, otherwise
          falls back to "cdecl". 

     In many cases, '"cdecl"' is the best choice. Exceptions to this
     include, X86 architectures and in particular Microsoft Windows
     platforms. 

     *WARNING*: non-X86 platforms are immune against wrong calling
     conventions, as there is only one.

     The calling convention is defined during compilation of shared
     libraries.  One specifies the calling convention using function
     prototype attributes such as  '__attribute__((stdcall))' or
     '__stdcall' for short.

     On X86 Architectures, the _fastcall_ and _thiscall_ (C++) calling
     convention differ  regarding Microsoft Visual C++ and the GCC
     compilers.  '"fastcall.msvc"' and '"thiscall.msvc"' are used for
     the Microsoft Visual C++ compiled code, while '"fastcall.gcc"' and
     '"fastcall.gcc"' use GCC compiled code.

_N_o_t_e:

     When invoking a foreign function calls, the address, calling
     convention and  type information for arguments and return values
     *MUST* match with  the compiled function.  Otherwise the
     invocation can lead to a *fatal system crash*.

     Calling functions via dyncall is very TYPE UNSAFE. Some safety is
     achieved. Dyncall does not perform any call, if you missed the
     arity of the function given with the signature and probably fails
     on several type-incompatibilities. But in general, there is no
     safe way to test if the pointer given, is a valid function
     pointer. Thus, this package can cause unexpected behaviour if the
     user is not aware of what she is doing. USE ON YOUR OWN RISK.

_R_e_f_e_r_e_n_c_e_s:

     Adler, D., Philipp, T. (2008) _DynCall Library_.  <URL:
     http://dyncall.org>

_S_e_e _A_l_s_o:

     'getNativeSymbolInfo' and '.dynfind'.  '.C','.Call',,'.External'

_E_x_a_m_p_l_e_s:

     # load 'R' dynport
     libR <- .dynload("R")
     reg.finalizer(libR, .dynunload)
     .dynfind(.libR, "") 
     # load platform-specific standard C DLL
      
     clibname <- "libc"
     if (.Platform$OS.type == "windows") clibname <- "msvcrt"
     if (.Platform$OS.type == "darwin") clibname <- "libc.dylib"
     if (.Platform$OS.type == "linux") clibname <- "libc.so.6"

     dyn.load(clibname)
     sqrt.ptr <- getNativeSymbolInfo("sqrt")
     mysqrt <- function(x) .dyncall.cdecl(sqrt.ptr, "d)d", x)

     aDouble <- 144
     anInteger <- 144L

     mysqrt(aDouble)
     mysqrt(anInteger)

     clib <- rdcLoad(clibname)

     # call sqrt function

     sqrt.fp <- rdcFind(clib,"sqrt")
     print( rdcCall(sqrt.fp, "d)d", 144) )

