0

質問のフォローアップとして:Ruby with Swig:NameError:初期化されていない定数

ルビーでQxtライブラリ(つまりQxtGlobalShortcut )を使用しようとしています。

提案されているように:Ruby内からC ++関数を呼び出すにはどうすればよいですか? swigラッパーを作成しましたが、生成されたライブラリを使用しようとすると、エラーが発生します。

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でラッパーを生成するために以下を使用しました:

qxtglobalshortcut.hのコンテンツはSwigで解析できないため、次のコンテンツを使用して簡略化されたバージョン(使用する必要のあるすべての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

スウィッグで生成された出力については、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>'
4

1 に答える 1

1

これはもっとトリッキーです。文字列への参照が見られないため、TypeError は非常に奇妙です。

それにもかかわらず、この gist https://gist.github.com/phurni/5081001を使用して、生成された .cxx ファイルにパッチを適用することができます。printf()ご覧のとおり、への呼び出しをトレースするためにの束を追加するだけです#initialize。このパターンに従って追跡することができます。おそらく、質問を編集してさらに情報を追加するか、irb セッションを更新します (トレースを表示します)。

アップデート

要するに、あなたが生成した Qxt lib とあなたが使用している Qt ruby​​ lib は、同じバージョンの SWIG によって生成されていないようです。これは分離されたライブラリでは問題になりませんが、Qxt ライブラリは Qt ライブラリと相互運用するため (Qt でラップされたオブジェクトである ui 引数を独自の Qxt でラップされたオブジェクトに渡します)、両方を同じバージョンでラップする必要があります。 (少なくともマイナー?)SWIGの。

技術的な詳細に戻る: 例外が発生したのは、SWIG_ConvertPtr1984 行目の の呼び出しであり、これが を呼び出しますSWIG_Ruby_MangleStr@__swigtype__この関数は、コードにある渡された引数でインスタンス変数を取得しようとしuiます。これは、渡された引数を (C++ 側で) 型チェックできるようにするためです。この変数はnil(そのような変数を使用せずに別の方法でラップされたQtからのものであるため)、SWIG_Ruby_MangleStrWANTSのコードはそれを文字列に変換するようです。

結論:

SWIG のどのバージョンが既存のライブラリをラップしているかを判断する方法がわかりません。見つかった場合は、Qt ライブラリをラップしたバージョンを取得し、そのバージョンを使用して Qxt ライブラリをラップすることができます。

もう 1 つの方法は、既知のバージョンの SWIG を使用して Qt ライブラリを生成し、Qxt ライブラリに対して同じことを行うことです。

于 2013-03-04T09:19:24.303 に答える