SWIG 将 C 指针字符串值转换为 TCL 字符串
SWIG convert C-Pointer stringvalue to tcl string
由于我对 C 和 SWIG 的了解有限,我无法采用任何 public 示例将 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) %{
= &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_stringout2
Itla_Get_Model_Version= _f0a759f8d9550000_p_stringout2
所以我最终需要取消对指针的引用...
但是不知道怎么成功.....
C 函数已给定,无法修改!
有人知道怎么做吗?
如果您的字符串基本上是 ASCII 或 UTF-8,您需要做的就是告诉 SWIG 您的函数已经分配了正在 returning 的字符串。有关详细信息,请参阅 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, particularly ones of the Tcl variety 的时候了。正确编写类型映射取决于理解您正在生成的值的语义 and/or 消耗 和 您正在使用的语言的语义。假设你想要包装,这里有一个非常简单的输出类型映射,可能工作:
%typemap(out) stringout2* {
Tcl_SetObjResult(interp, Tcl_NewStringObj(->modelvers, -1));
free();
}
您的函数还需要通过return pointer2;
修改为return一个stringout2*
,而不是stringout2
因为否则你 将 在每次调用时泄漏内存。你可以return一个stringout2
,但是如果你这样做那么你应该不用[=19分配它=],而是将其作为结构直接保存在局部变量中。
在这种情况下,您要使用的类型映射是:
%typemap(out) stringout2 {
Tcl_SetObjResult(interp, Tcl_NewStringObj(.modelvers, -1));
}
(注意类型不同,访问字段不同,缺少free
。)
如果确实如此,您的结构应该声明为包含 const char *
。
如果您有不同编码的字符串(并且它不是 ISO 8859-1,您可以使用 Tcl_NewByteArrayObj
作弊并使用二进制字符串;这也是您想要分块的原因的二进制数据)然后你需要使用 Tcl_ExternalToUtfDString
编写一个类型映射,并且样板代码的数量会增加。 Tcl 坚持 它的内部字符串(几乎)是 UTF-8,ASCII 也可以,因为那是一个严格的子集;其他所有内容都必须转换。
如果这是您的需要,请再问一个问题。您可能正在处理 ASCII 或二进制数据,所以在请求之前我将单独进行编码转换(相当复杂!)。
由于我对 C 和 SWIG 的了解有限,我无法采用任何 public 示例将 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) %{
= &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_stringout2 Itla_Get_Model_Version= _f0a759f8d9550000_p_stringout2
所以我最终需要取消对指针的引用... 但是不知道怎么成功.....
C 函数已给定,无法修改!
有人知道怎么做吗?
如果您的字符串基本上是 ASCII 或 UTF-8,您需要做的就是告诉 SWIG 您的函数已经分配了正在 returning 的字符串。有关详细信息,请参阅 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, particularly ones of the Tcl variety 的时候了。正确编写类型映射取决于理解您正在生成的值的语义 and/or 消耗 和 您正在使用的语言的语义。假设你想要包装,这里有一个非常简单的输出类型映射,可能工作:
%typemap(out) stringout2* {
Tcl_SetObjResult(interp, Tcl_NewStringObj(->modelvers, -1));
free();
}
您的函数还需要通过return pointer2;
修改为return一个stringout2*
,而不是stringout2
因为否则你 将 在每次调用时泄漏内存。你可以return一个stringout2
,但是如果你这样做那么你应该不用[=19分配它=],而是将其作为结构直接保存在局部变量中。
在这种情况下,您要使用的类型映射是:
%typemap(out) stringout2 {
Tcl_SetObjResult(interp, Tcl_NewStringObj(.modelvers, -1));
}
(注意类型不同,访问字段不同,缺少free
。)
如果确实如此,您的结构应该声明为包含 const char *
。
如果您有不同编码的字符串(并且它不是 ISO 8859-1,您可以使用 Tcl_NewByteArrayObj
作弊并使用二进制字符串;这也是您想要分块的原因的二进制数据)然后你需要使用 Tcl_ExternalToUtfDString
编写一个类型映射,并且样板代码的数量会增加。 Tcl 坚持 它的内部字符串(几乎)是 UTF-8,ASCII 也可以,因为那是一个严格的子集;其他所有内容都必须转换。
如果这是您的需要,请再问一个问题。您可能正在处理 ASCII 或二进制数据,所以在请求之前我将单独进行编码转换(相当复杂!)。