2013-12-15 5 views
3

Я смотрел на то, как Red/System перехватывает с функциями библиотеки C из Windows, библиотек DLL, Linux/с Android .so разделяемых библиотек, и OS/X .dylib с #import синтаксисом:Как создать привязку Red/System к функции, которая принимает указатель на указатель?

#import [ 
    "libc.so.6" cdecl [ 

     allocate: "malloc" [ 
      size [integer!] 
      return: [byte-ptr!] 
     ] 

     free: "free" [ 
      block [byte-ptr!] 
     ] 

     /* ... */ 
] 

работ для всех основные типы, но что вы делаете, когда функция хочет указатель на указатель? Например, что если вы пытаетесь связать с чем-то вроде getline(), который имеет прототип:

ssize_t getline(char **lineptr, size_t *n, FILE *stream); 

Один из способов вызова этого (как я хочу назвать это ...), где поступающая lineptr является не предварительно выделенный буфер, а скорее null. В этом случае getline выделяет вам буфер и изменяет char *, поэтому он больше не равен null.

В первой попытки, я сделал:

getline: "getline" [ 
    lineptr [byte-ptr!]  ;-- char ** 
    n [pointer! [integer!]] ;-- size_t * 
    stream [byte-ptr!]  ;-- FILE * 
    return: [integer!]  ;-- ssize_t 
] 

Но поскольку не существует такой вещи, как pointer! [c-string!] или подобное, я не вижу, как это назвать. Могу ли я получить адрес локальной переменной c-string! и передать ее как byte-ptr! как-нибудь?

ответ

7
Red/System [ 
    Title: "derp" 
] 

#import [ 
    LIBC-file cdecl [ 
     _fdopen: "fdopen" [ 
      fd [integer!] 
      type [c-string!] 

      return: [pointer! [byte!]] 
     ] 

     _getline: "getline" [ 
      line [pointer! [integer!]] 
      n  [pointer! [integer!]] 
      stream [pointer! [byte!]] 

      return: [integer!] 
     ] 
    ] 
] 

getline: func [ 
    stream [pointer! [byte!]] 
    return: [c-string!] 

    /local 
     line [integer!] 
     n [integer!] 
] [ 
    line: 0 
    n: 0 

    _getline :line :n stream 
    as c-string! line 
] 

stream: _fdopen 0 "r" 
line: getline stream 

print line 

Это работает.

+0

Спасибо! Это работает, хотя возврат из getline LIBC - это длина строки, полученной (а не строка), поэтому она будет целочисленной ... вы можете отредактировать свои ответы (я тоже могу). Но я позволю тебе это сделать. :-) – HostileFork

+0

Действительно, спасибо, отредактирован. –

2

В мире мало Красной документации, один фактический Red/System Specification Document очень полезно, и этот раздел содержит ответ косвенно в другом примере:

p: declare pointer! [byte!]   ;-- char *p; 

, который приведет:

getline: "getline" [ 
    lineptr [pointer! [byte!]] ;-- *char * 
    n [pointer! [integer!]]  ;-- *size_t 
    stream [pointer! [byte!]] ;-- *char 
    return: [integer!]   ;-- ssize_t 
] 
+0

Хорошо упоминать ссылку. Наверное, главное, что я на самом деле не придумал, было красное/системное приложение GET-WORD! означает «адрес». – HostileFork

 Смежные вопросы

  • Нет связанных вопросов^_^