我有疑问,因为我没有想法。我有用 SWIG 包装的 c 库。我不使用 FFI,因为我不想在我的 GEM 中存在任何第三方依赖项。问题是我遇到了一些问题。我在 C 中有一个函数,它创建 char* 缓冲区并返回它的大小。我需要返回缓冲区和缓冲区本身的 ruby 大小。对于 size_t 不是大问题,我可以将它作为 int 存储在 ruby 端,并稍后返回到 C 后将其转换,但我对 char* 有问题。
当我将 char* 从 C 返回到 ruby 时,它会转换为字符串。所以我不能再将它作为 char* 返回到 C。我试图做一些肮脏的事情,比如获取 char* 的内存地址,将其存储为字符串并将其传递回 C,但两者都不起作用。
什么是用例。我需要使用第 3 方 C 库链接两个 ruby 线程。因此,我需要在线程一上创建链接实例,并将 char* 和 size_t 指针传递给线程2,这是一个初始化链接。所以没有办法改变这种方法。
问题是,是否可以传递对 char* 指针 C -> Ruby -> C 的引用以及如何做到这一点。我两天以来一直在寻找解决方案,但我这里没有好的想法。
提前谢谢:)
将 char* 从 C 返回到 Ruby 的示例函数
char* link_rb() {
size_t in_process_link_size = 0;
link_create(NULL, 0, &in_process_link_size);
unsigned char* in_process_link = NULL;
if (in_process_link_size != 0) {
in_process_link = (unsigned char*)malloc(in_process_link_size);
if (in_process_link != NULL)
in_process_link_size = link_create(in_process_link, in_process_link_size, NULL);
}
return in_process_link;
}
link_create 不是我的函数,我需要在这里使用它(无法更改它)。
在另一边我需要做这样的事情:
tracer_handle_t tracer_create_rb(unsigned char const* link) {
size_t link_size = 40;
char* buffer = (char*) &link;
size_t tracer = inprocesslinktracer_create(link, link_size);
return tracer;
}
inprocesslinktracer_create 也不是我的功能。来自SDK
现在假设我将仅返回 char* 并传递它以及单个参数。一般来说,我还需要缓冲区的大小,我可以转到此处的结构,但首先我想在这里弄清楚它。
问题是,是否可以传递对 char* 指针的引用 C -> Ruby -> C
是的。
SWIG 默认情况下假设应包装
char *
类型的对象,以便访问所指向的数据,而不是指针本身。这与它处理其他指针的方式不同。但是,SWIG 的映射行为可以通过 Typemaps 进行自定义,并且在必要时,您可以通过编写垫片来帮助它(所提供的示例不需要)。
示例代码可以使用简单的输入和输出类型映射来提供:
mymodule.i
%module mymodule
/* Relying on SWIG to #include <ruby.h> */
%typemap(in) unsigned char const *AS_NUMBER {
$1 = (unsigned char const *) NUM2ULL($input);
}
%typemap(out) char *link_rb {
$result = ULL2NUM((unsigned long long) $1);
}
%{
#include "tracer.h"
%}
/*
* We don't want SWIG to process all of tracer.h. This is what we actually
* want wrapped, and any additional declarations needed to fully define that.
* These declarations need to be compatible with the those in tracer.h:
*/
#include <stddef.h>
typedef size_t tracer_handle_t;
char *link_rb(void);
tracer_handle_t tracer_create_rb(unsigned char const *AS_NUMBER);
in
类型映射指定匹配给定名称和数据类型的参数或对象的 Ruby -> C 转换。类似地, out
类型映射指定与给定名称和数据类型匹配的返回值或对象的 C -> Ruby 转换。请注意,AS_NUMBER
仅具有该接口文件赋予它的意义。这对 SWIG 来说并不特别。
一般来说,我还需要缓冲区的大小,我可以转到此处的结构,但首先我想在这里弄清楚它。
随你喜欢。