[英]Ruby: `gsub': can't convert nil into String (TypeError)
[英]Ruby and Swig: TypeError: can't convert nil into String
作為問題的后續: 帶Swig的Ruby:NameError:未初始化的常量
我正在嘗試在ruby中使用Qxt庫 (即QxtGlobalShortcut )。
如上建議的那樣: 如何從我創建的Swig包裝器中的ruby中調用C ++函數 ,但是當嘗試使用生成的庫時,我陷入了錯誤:
irb(main):005:0> shortcut = QxtGlobalShortcut::QxtGlobalShortcut.new ui
TypeError: can't convert nil into String
from (irb):5:in `initialize'
from (irb):5:in `new'
from (irb):5
from /usr/bin/irb:12:in `<main>'
我完整的irb會話輸出:
$ irb
irb(main):001:0> require 'Qt4'
=> true
irb(main):002:0> require 'QxtGlobalShortcut'
=> true
irb(main):003:0> app = Qt::Application.new ARGV
=> #<Qt::Application:0x00000002e02598 objectName="irb">
irb(main):004:0> ui = Qt::Widget.new
=> #<Qt::Widget:0x00000002f9e2a8 objectName="", x=0, y=0, width=640, height=480>
irb(main):005:0> shortcut = QxtGlobalShortcut::QxtGlobalShortcut.new ui
TypeError: can't convert nil into String
from (irb):5:in `initialize'
from (irb):5:in `new'
from (irb):5
from /usr/bin/irb:12:in `<main>'
我使用以下方法在swig中生成包裝器:
由於Swig無法解析qxtglobalshortcut.h內容,因此我創建了簡化的版本(包含我需要使用的所有API):
#ifndef QXTGLOBALSHORTCUT_H
#define QXTGLOBALSHORTCUT_H
#include "qxtglobal.h"
#include <QObject>
#include <QKeySequence>
class QxtGlobalShortcut : public QObject
{
public:
explicit QxtGlobalShortcut(QObject* parent);
explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0);
virtual ~QxtGlobalShortcut();
QKeySequence shortcut() const;
bool setShortcut(const QKeySequence& shortcut);
bool isEnabled() const;
};
#endif // QXTGLOBALSHORTCUT_H
其余的幾乎是標准的:
$ cat QxtGlobalShortcut.i
%module QxtGlobalShortcut
%{
/* Includes the header in the wrapper code */
#include "/usr/include/QxtGui/QxtGlobalShortcut"
%}
/* Parse the header file to generate wrappers */
%include "qxtglobalshortcut.h"
$ cat extconf.sh
require 'mkmf'
dir_config('QxtCore')
dir_config('QxtGui')
dir_config('QtCore')
dir_config('QtGui')
create_makefile('QxtGlobalShortcut')
$ cat wrapper.sh
swig -c++ -ruby QxtGlobalShortcut.i
ruby extconf.rb --with-QxtCore-include=/usr/include/QxtCore/ --with-QxtGui-include=/usr/include/QxtGui/ --with-QtCore-include=/usr/include/QtCore/ --with-QtGui-include=/usr/include/QtGui/
make
sudo make install
有關Swig生成的輸出,請參見: QxtGlobalShortcut_wrap.cxx 。
知道如何解決嗎? 謝謝。
更新:
提供基於@PascalHurni擴展日志記錄差異的irb輸出:
$ irb
irb(main):001:0> require 'Qt4'
=> true
irb(main):002:0> require 'QxtGlobalShortcut'
=> true
irb(main):003:0> app = Qt::Application.new ARGV
=> #<Qt::Application:0x00000001d79d98 objectName="irb">
irb(main):004:0> ui = Qt::Widget.new
=> #<Qt::Widget:0x00000001f16818 objectName="", x=0, y=0, width=640, height=480>
irb(main):005:0> shortcut = QxtGlobalShortcut::QxtGlobalShortcut.new ui
_wrap_new_QxtGlobalShortcut ENTERING with 0 arguments
TypeError: can't convert nil into String
from (irb):5:in `initialize'
from (irb):5:in `new'
from (irb):5
from /usr/bin/irb:12:in `<main>'
此外,我看到argc似乎有問題,因此發布了make輸出(不確定是否有幫助):
creating Makefile
g++ -I. -I/usr/include/x86_64-linux -I/usr/include/ruby/backward -I/usr/include -I. -I/usr/include/QtGui/ -I/usr/include/QtCore/ -I/usr/include/QxtGui/ -I/usr/include/QxtCore/ -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -mtune=generic -fPIC -m64 -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -mtune=generic -o QxtGlobalShortcut_wrap.o -c QxtGlobalShortcut_wrap.cxx
QxtGlobalShortcut_wrap.cxx: In function ‘void SWIG_Ruby_define_class(swig_type_info*)’:
QxtGlobalShortcut_wrap.cxx:1517:9: warning: variable ‘klass’ set but not used [-Wunused-but-set-variable]
QxtGlobalShortcut_wrap.cxx: In function ‘void SWIG_InitializeModule(void*)’:
QxtGlobalShortcut_wrap.cxx:2206:21: warning: statement has no effect [-Wunused-value]
QxtGlobalShortcut_wrap.cxx: In function ‘VALUE _wrap_new_QxtGlobalShortcut(int, VALUE*, VALUE)’:
QxtGlobalShortcut_wrap.cxx:1973:75: warning: ‘argc’ is used uninitialized in this function [-Wuninitialized]
rm -f QxtGlobalShortcut.so
g++ -shared -o QxtGlobalShortcut.so QxtGlobalShortcut_wrap.o -L. -L/usr/lib64 -L. -Wl,-z,relro -rdynamic -Wl,-export-dynamic -m64 -lruby -lpthread -lrt -ldl -lcrypt -lm -lc
/usr/bin/mkdir -p /usr/local/lib64/ruby/site_ruby
/usr/bin/install -c -m 0755 QxtGlobalShortcut.so /usr/local/lib64/ruby/site_ruby
有任何想法嗎?
更新2:
提供基於@PascalHurni擴展日志記錄差異(版本2)的irb輸出:
$ irb
irb(main):001:0> require 'Qt4'
=> true
irb(main):002:0> require 'QxtGlobalShortcut'
=> true
irb(main):003:0> app = Qt::Application.new ARGV
=> #<Qt::Application:0x000000017b4e30 objectName="irb">
irb(main):004:0> ui = Qt::Widget.new
=> #<Qt::Widget:0x00000001952940 objectName="", x=0, y=0, width=640, height=480>
irb(main):005:0> shortcut = QxtGlobalShortcut::QxtGlobalShortcut.new ui
_wrap_new_QxtGlobalShortcut ENTERING with 1 arguments
_wrap_new_QxtGlobalShortcut before ptr convert for _wrap_new_QxtGlobalShortcut__SWIG_0 TYPE=12
TypeError: can't convert nil into String
from (irb):5:in `initialize'
from (irb):5:in `new'
from (irb):5
from /usr/bin/irb:12:in `<main>'
這個比較棘手。 我看不到對字符串的任何引用,因此TypeError確實很奇怪。
但是,您可以使用此要旨https://gist.github.com/phurni/5081001修補生成的.cxx文件。 如您所見,它只是添加了一堆printf()
來跟蹤對#initialize
的調用。 您可以按照此模式進行跟蹤,可以使用更多信息來編輯您的問題,也可以使用更新的irb會話(顯示跟蹤信息)。
更新
簡而言之,似乎您生成的Qxt庫和您使用的Qt紅寶石庫不是由同一版本的SWIG生成的。 這對於分離的庫來說不是問題,但是因為您的Qxt庫將與Qt庫互操作(您將ui參數(這是Qt包裝的對象傳遞給自己的Qxt包裝的對象)),所以兩者都必須由相同的版本包裝(至少是未成年人?)。
返回技術細節:引發的異常來自第1984行的SWIG_ConvertPtr
的調用,該調用又依次調用SWIG_Ruby_MangleStr
。 此函數嘗試在傳遞的參數(您的代碼中的ui
上獲取實例變量@__swigtype__
。 這是為了能夠(在C ++方面)對傳遞的參數進行類型檢查。 似乎此變量為nil
(因為它來自Qt,而未使用此類變量進行了包裝),並且SWIG_Ruby_MangleStr
的代碼將其轉換為String。
我不知道一種確定SWIG版本包裝現有lib的方法,如果找到一個版本,您可能會得到包裝Qt lib的版本並使用該版本包裝Qxt lib。
另一種方法是使用已知版本的SWIG生成Qt庫,並對Qxt庫執行相同的操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.