SWIG конвертировать C -Строковое значение строки в строку tcl - PullRequest
1 голос
/ 18 марта 2020

из-за моих ограниченных знаний в C и SWIG я не смог принять ни один пример публикации c для преобразования символов c -пунктов в строки tcl .... Я всегда застреваю в проблеме, моя переменная tcl просто не разыменовывается следующим образом:

tcl_str = _30e84c05ef550000_p_stringout2

string_pointer. c

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "string_pointer.h"

stringout2  Itla_Get_Model_Version (int laser, char * mv_string)
   {
       stringout2 * pointer2;       
       char *mod_ver ="PPCL600";
       pointer2 = malloc( sizeof(stringout2) );
       pointer2-> modelvers= *mod_ver;
       printf ( "Itla_Get_Model_Version : read   %s   \n",  mod_ver );
       return  *pointer2 ;
   }   

string_pointer.h

#include <sys/types.h>
#include <sys/resource.h>


typedef struct {
      char      * modelvers;
} stringout2;

stringout2  Itla_Get_Model_Version   (int laser, char * mv_string) ;

string_pointer.swig

/* File : string_pointer.swig */
%module string_pointer

%{
#include "string_pointer.h"
%}

%include "typemaps.i"
%include "cpointer.i"
%include "cstring.i"

%typemap(argout) char* (char tmp) %{
    $1 = &tmp;
%}

stringout2  Itla_Get_Model_Version    (int laser, char *OUTPUT) ;

%include "string_pointer.h"

test.tcl

load ./string_pointer.so

proc test { laser  } {

scan [Itla_Get_Model_Version $laser ] %s  a 
puts "$a "
return $a
}

set name [test 1 ]
puts "Itla_Get_Model_Version= $name"

при выполнении tcl-скрипта вы получаете:

Itla_Get_Model_Version : read   PPCL600 
_f0a759f8d9550000_p_stringout2 
Itla_Get_Model_Version= _f0a759f8d9550000_p_stringout2

так что мне наконец нужно разыменовать указатель на его значение ... Но я не знаю, как добиться успеха .....

Функция C задана и не может быть изменена!

Кто-нибудь там знает, как это сделать?

1 Ответ

0 голосов
/ 18 марта 2020

Если ваши строки в основном ASCII или UTF-8, все, что вам нужно сделать, это сообщить SWIG, что ваша функция выделила строку, которую она возвращает. Подробнее см. документы SWIG на C строках.

ваш код. c

char *Itla_Get_Model_Version (int laser, char * mv_string) {
    // I assume this is a proxy for something more complicated...
    const char *mod_ver ="PPCL600";
    size_t len = strlen(mod_ver) + 1;

    char *output = malloc(len);
    memcpy(output, mod_ver, len);
    printf ( "Itla_Get_Model_Version : read   %s   \n",  mod_ver );
    return output;
}

yourcode.h

char *Itla_Get_Model_Version(int laser, char * mv_string);

yourcode.swig

/* Tell SWIG that this function returns something to be freed */
%newobject Itla_Get_Model_Version

/* And now we can use the standard C header */
%include "yourcode.h"

Если вышеприведенное простое решение не работает…

Все становится намного сложнее, если вы используете другую кодировку для строк или если вы заключаете их в структуру (как вы делали в своем вопросе). В этот момент вам понадобится карта типов , особенно из Tcl . Правильное написание таблицы типов зависит от понимания семантики значений, которые вы производите и / или потребляющих и семантики языка, который вы используете. Предполагая, что вы хотите обтекание, вот очень простая выходная карта типов, которая может работать:

%typemap(out) stringout2* {
    Tcl_SetObjResult(interp, Tcl_NewStringObj($1->modelvers, -1));
    free($1);
}

Ваша функция также нуждается в , которую нужно изменить вернуть stringout2*, выполнив return pointer2;, а не stringout2, так как в противном случае у вас будет утечка памяти при каждом вызове. Вы можете вернуть stringout2, но если вы делаете это, вы должны не выделить его с помощью malloc, а хранить его как структуру непосредственно в локальной переменной.

В этом случае вы использовали бы типографскую карту:

%typemap(out) stringout2 {
    Tcl_SetObjResult(interp, Tcl_NewStringObj($1.modelvers, -1));
}

(обратите внимание на другой тип, другой доступ к полю и отсутствие free.)
И ваша структура должна быть объявлена ​​как содержащая const char *, если это действительно так.


Если у вас есть строки в другой кодировке (и это не ISO 8859- 1, для которого вы можете обмануть и использовать двоичную строку, используя Tcl_NewByteArrayObj (это также то, что вы хотите для обработки фрагмента двоичных данных), тогда вам нужно написать карту типов, используя Tcl_ExternalToUtfDString, и количество шаблонов код идет вверх. Tcl настаивает , что его внутренние строки находятся в (почти) UTF-8, и ASCII тоже в порядке, поскольку это строгое подмножество; все остальное необходимо преобразовать.

Задайте другой вопрос, если это то, что вам нужно. Вы, вероятно, имеете дело либо с ASCII, либо с двоичными данными, поэтому я оставлю (чуть более сложное!) Преобразование кодировки в покое, пока не будет запрошено.

...