SWIG将C指针的字符串值转换为tcl字符串

问题描述 投票:1回答:1

由于我对C和SWIG的了解有限,我无法设法采用任何公共示例将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:读取PPCL600_f0a759f8d9550000_p_stringout2Itla_Get_Model_Version = _f0a759f8d9550000_p_stringout2

所以我最终需要将Pointer取消引用其值...但是我不知道如何成功.....

C功能已给出,无法修改!

外面有人知道该怎么做吗?

c pointers char tcl swig
1个回答
0
投票

如果您的字符串基本上是ASCII或UTF-8,您需要做的就是告诉SWIG您的函数已经分配了要返回的字符串。有关详细信息,请参见C字符串上的the SWIG docs

yourcode.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"

如果上面的简单解决方案不起作用…

如果您对字符串使用不同的编码,或者将它们包装在结构中(就像您在问题中所做的那样,则事情会变得更加复杂。那是您需要typemap的时候,尤其是Tcl variety的时候。正确编写一个类型图取决于对所产生和/或使用的值的语义的理解和/或正在使用的语言的语义。假设您要包装,这是一个very

简单的输出类型映射,它[可以工作:%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


insists

它的内部字符串在(几乎)UTF-8中,并且ASCII也可以,因为这是一个严格的子集;其他所有[[必须都将被转换。

问另一个问题,是否就是您所需要的。您可能正在处理ASCII或二进制数据,因此在请求之前,我将不谈编码(非常复杂!)编码转换。

© www.soinside.com 2019 - 2024. All rights reserved.