由于我对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功能已给出,无法修改!
外面有人知道该怎么做吗?
如果您的字符串基本上是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));
}
(请注意不同的类型,对该字段的不同访问以及缺少它的内部字符串在(几乎)UTF-8中,并且ASCII也可以,因为这是一个严格的子集;其他所有[[必须都将被转换。free
。]如果确实如此,则应将您的结构声明为包含const char *
。[如果您使用不同编码的字符串(并且不是ISO 8859-1,则可以使用
Tcl_NewByteArrayObj
作弊并使用二进制字符串;这也是您要在其上提取大量二进制数据的目的)那么您将需要使用Tcl_ExternalToUtfDString
编写一个类型映射,样板代码数量也会增加。 Tcl
insists
问另一个问题,是否就是您所需要的。您可能正在处理ASCII或二进制数据,因此在请求之前,我将不谈编码(非常复杂!)编码转换。