c - SWIG 将 C 指针字符串值转换为 tcl 字符串
问题描述
由于我在 C 和 SWIG 方面的知识有限,我无法采用任何公共示例将 c 指针字符转换为 tcl 字符串....我总是陷入我的 tcl 变量没有被取消引用的问题这个 :
tcl_str = _30e84c05ef550000_p_stringout2
字符串指针.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 ;
}
字符串指针.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"
测试.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-function 是给定的,不能修改!
有大佬知道怎么弄吗?
解决方案
如果您的字符串基本上是 ASCII 或 UTF-8,您需要做的就是告诉 SWIG 您的函数已分配它返回的字符串。有关详细信息,请参阅关于 C 字符串的 SWIG 文档。
你的代码.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;
}
你的代码.h
char *Itla_Get_Model_Version(int laser, char * mv_string);
你的代码.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"
如果上述简单的解决方案不起作用……</h2>
如果您对字符串使用不同的编码或者将它们包装在结构中(就像您在问题中所做的那样),事情会变得更加复杂。那是您需要typemap的时候,尤其是Tcl 种类的 typemap 。正确编写类型映射取决于理解您正在生成和/或使用的值的语义以及您正在使用的语言的语义。假设您想要包装,这里有一个非常简单的输出类型映射,它可能会起作用:
%typemap(out) stringout2* {
Tcl_SetObjResult(interp, Tcl_NewStringObj($1->modelvers, -1));
free($1);
}
您的函数还需要stringout2*
修改为通过执行返回 a return pointer2;
,而不是 a stringout2
,否则您将在每次调用时泄漏内存。您可以返回 a stringout2
,但如果这样做,则不应将其分配给malloc
,而应将其作为结构直接保存在局部变量中。
在这种情况下,您要使用的类型映射是:
%typemap(out) stringout2 {
Tcl_SetObjResult(interp, Tcl_NewStringObj($1.modelvers, -1));
}
(注意不同的类型,对字段的不同访问,以及缺少free
.)如果确实如此,
则应将您的结构声明为包含 a 。const char *
如果您有不同编码的字符串(并且它不是 ISO 8859-1,您可以使用它作弊并使用二进制字符串Tcl_NewByteArrayObj
;这也是您将一大块二进制数据覆盖的内容),那么您将需要使用 编写类型Tcl_ExternalToUtfDString
图,样板代码的数量就会增加。Tcl坚持它的内部字符串(几乎)是 UTF-8 格式,ASCII 也可以,因为这是一个严格的子集;其他一切都必须转换。
问另一个问题,如果那是你需要的。您可能正在处理 ASCII 或二进制数据,因此在请求之前,我将单独保留(相当复杂一点!)编码转换。
推荐阅读
- jquery - Jquery 不能在 Angular 6 中工作错误:ENOENT:没有这样的文件或目录,打开 '...\node_modules\jquery\dist\jquery.min.js'
- apache-flink - Flink EMR 安装
- node.js - 并行运行多个节点任务
- javascript - 使用传播添加到对象中的所有值
- sparql - 清除命名图的最有效方法?
- php - XAMPP PDO Sqlite 目录
- swift - iPhone X - UICollectionViewController 自动布局
- python - 使用 python 和 pandas 回测交易策略 - 一次只识别一个未平仓头寸
- docker - 无法在 Artifactory 中登录 docker 注册表
- php - 如何在 PHP 中生成具有不同元素编号的多个数组中的所有项目组合