簡體   English   中英

Ruby和Swig:TypeError:無法將nil轉換為String

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM