由於工作版權問題,我無法發佈我的實際代碼,所以我會嘗試用簡單的示例代碼顯示我的問題。Ruby C擴展rb_str_new2似乎返回false
我有一個C擴展它的簡化版本是這樣的:
#include <ruby.h>
#include <termios.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
VALUE test(VALUE self, VALUE string);
void Init_module_name() {
module_name = rb_define_module("Modulename");
c_modulename = rb_define_class_under(modulename, "Class", rb_cObject);
rb_define_method(c_modulename, "test", test, 1);
e_ModuleNameError = rb_define_class_under(modulename, "Error", rb_eStandardError);
}
VALUE test(VALUE self, VALUE string) {
char *c_string = StringValueCStr(string);
int fd = open(c_string, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd == -1) {
rb_raise(e_ModuleNameError, "Failed to open file");
}
if (!isatty(fd)) {
rb_raise(e_ModuleNameError, "File is not a tty");
}
struct termios config;
int termios_ret = init_termios(config, fd)
if (termios_ret != OK) { // OK defined by enum in modulename's header
close(fd);
rb_raise(e_ModuleNameError, "Termios init failed.");
}
int success = write(fd, "I'm a string", str_length);
if (success < str_length) {
close(fd);
rb_raise(e_ModuleNameError, "Failed to write to file.");
}
close(fd);
return rb_str_new2("Success");
}
然後,要求這看起來Ruby代碼,如:
require 'modulename'
class ModuleName
attr_acessor :file
def initialize(file)
@file = file
@object = Modulename::Class.new
end
def test
@object.test @file
end
end
然後叫我的生產項目,如:
require "modulename_ruby_file"
x = ModuleName "/dev/pts/1"
x.test
這是有趣的事情。當我在生產中運行此代碼時,上面x.test的返回值是false(如字面意義上的值false,而不是字符串)。此外,寫入文件永遠不會發生。但是,如果我在一些簡化的測試代碼中執行它,它就會像預期的那樣返回字符串「Success」,並且寫入確實完成。
有誰知道,將導致此功能不執行寫操作,並返回false任何情況呢?我已經嘗試過對它進行救援,以防它拋出一個rb_raises,但它似乎不是。
我和我的3團隊的其他成員看着這一切的下午,並沒有找到答案。
我認爲示例代碼需要一些編輯。例如,「@ console」是什麼?它實際上是「@ object」嗎? –
就我所見,您的示例C擴展方法'test'將返回字符串'Success',或者引發錯誤。你真的能夠使用這段代碼複製錯誤嗎?我懷疑你選擇提取的部分很可能實際上並不能證明你的問題。 –
事實上,我期望有一個環境問題,或者非常簡單的事情,比如在部署到生產環境時不重新構建擴展。 –