0

ヘッダー ファイル (HKnotVector.h) に完全に実装されているクラスがあります。いくつかの std_vector.i タイプマップを定義する SWIG インターフェイス ファイル (HKnotVector.i) もあります。別のファイル (common.h) から HKnotVector.h が必要とする定義があります。common.h の関連部分を HKnotVector.i にコピー アンド ペーストすると、すべてが完全に機能します。

#include "common.h"問題は、 HKnotVector.h 内に入ろうとしたときに発生します。SWIG と python は拡張機能をビルドできますが、次の警告が表示されます。HKnotVector.h:7: Error: Nothing known about namespace 'util'

HKnotVector.h の関連部分は次のとおりです。

/* file HKnotVector.h */
#include "common.h"
#include <vector>
#include <iostream>

using namespace std;
using namespace util;

namespace hbs
{
    class HKnotVector
    {
        public:
        HKnotVector( uint degree, const DoubleVec &knots )
            : mDeg( degree ), mKnots( knots )
        {
            getKVecData( mKnots, mGroups, mReverseGroups, mMultipleCount );
        }
        // A lot of missing code
        protected:
        uint mDeg;
        DoubleVec mKnots;
        IntVec mGroups;
        IntVecVec mReverseGroups;
        IntVec mMultipleCount;
        void getKVecData( const DoubleVec &knots, IntVec &knot_groups,
                          IntVecVec &reverse_knot_groups, IntVec &multiple_counts ) const
        {
            // Do cool stuff
        }
    };
}

common.h の関連部分:

/* file common.h */
#include <iostream>
#include <vector>

typedef unsigned int uint;

using namespace std;

namespace util
{
    typedef std::vector< double > DoubleVec;
    typedef std::vector< int > IntVec;
    typedef std::vector< IntVec > IntVecVec;
    // A whole bunch of more stuff
}

HKnotVector.i のすべて:

/* file HKnotVector.i */
%module hbspy
%{
#include "HKnotvector.h"
%}

%include "std_vector.i"
namespace std {
    %template(IntVec)    vector<int>;
    %template(DoubleVec) vector<double>;
    %template(IntVecVec) vector<vector<int> >;
}

%include "HKnotvector.h"

最後に、HKnotVector のインスタンスを作成しようとするテスト python ファイルがあります。

import hbspy

# Test HKnotVector
py_knots = [0., 0., 0., .25, .5, .75, 1., 1., 1.]
knots = hbspy.DoubleVec(py_knots)
print('knots object: %s\n\n\n' % knots)
kv = hbspy.HKnotVector(2, knots)

を使用してコンパイルしswig -c++ -python HKnotVector.i、拡張機能をビルドしてテスト ファイルを実行すると、次のようになります。

knots object: <hbspy.DoubleVec; proxy of <Swig Object of type 'std::vector< double > *' at 0x100499450> >

Traceback (most recent call last):
File "./doit", line 17, in <module>
  execfile('test.py')
File "test.py", line 18, in <module>
  kv = hbspy.HKnotVector(2, knots)
File "/Users/spencerlyon2/Research/HBS/hbs/swig/hbspy.py", line 249, in __init__
  this = _hbspy.new_HKnotVector(*args)
NotImplementedError: Wrong number or type of arguments for overloaded function 'new_HKnotVector'.
Possible C/C++ prototypes are:
  hbs::HKnotVector::HKnotVector()
  hbs::HKnotVector::HKnotVector(uint,DoubleVec const &)
  hbs::HKnotVector::HKnotVector(hbs::HKnotVector const &)

ノットを印刷すると、タイプが であることがstd::vector < double > *わかりtypdefますDoubleVecknots2 番目の「C/C++ プロトタイプ」を満たす必要があることが明らかな場合に、コンストラクターに渡すとこのエラーが発生する理由がわかりません。

関連するコードを common.h から HKnotVector.i に単純にコピーして貼り付けると、このエラーは発生しないことを強調したいと思います。

誰かが正しい道を歩むきっかけになるかもしれない 2 つの考えがあります。

  1. .i ファイルでswig を実行すると、名前空間について何も知られていないというエラーが表示されますutilDoubleVectypedef
  2. 私は(?)%include common.hどこかに行く必要があるかもしれないので、swigはそれについてすべて知っています。

編集 (5-11-13)

%include "common.h"HKnotVector.i (行のすぐ上) で実行しようとすると%include "../include/HKnotVector.h"、名前空間エラー ( HKnotVector.h:7: Error: Nothing known about namespace 'util') なしで拡張機能がビルドされますが、python はそれをインポートできません。でビルドした後に test.py を実行しようとすると、次のようになり%include "common.h"ます。

Traceback (most recent call last):
  File "test.py", line 10, in <module>
    import hbspy
  File "/Users/spencerlyon2/Research/HBS/hbs/swig/hbspy.py", line 26, in <module>
    _hbspy = swig_import_helper()
  File "/Users/spencerlyon2/Research/HBS/hbs/swig/hbspy.py", line 22, in swig_import_helper
    _mod = imp.load_module('_hbspy', fp, pathname, description)
ImportError: dlopen(/Users/spencerlyon2/Research/HBS/hbs/swig/_hbspy.so, 2): Symbol not found: __ZN4utillsERSoRKNS_4AxisE
  Referenced from: /Users/spencerlyon2/Research/HBS/hbs/swig/_hbspy.so
  Expected in: dynamic lookup

__ZN4utillsERSoRKNS_4AxisEが何かわかりませんが、拡張モジュールまたは SWIG によって定義された内部シンボルであると想定しています。


編集2 (5-11-13)

common.h に移動して、util名前空間を指定する行を削除し、HKnotVector.h の行をコメント アウトすると、using namespace util;すべてが機能します。

swig のドキュメントには、「C++ 名前空間のサポートは包括的です...」と「デフォルトのラッピング動作は、ターゲット言語の名前空間を平坦化することです。これは、すべての名前空間の内容が一緒にマージされることを意味します。結果のスクリプト言語モジュールで。」utilそれは私が望む動作のようです。つまり、グローバル名前空間にあるかのようにすべてにアクセスできるように Python になりたいと考えています。

この小さな例では、名前空間の指定を削除するのは単純明快です。ただし、これは、既に名前空間を深く使用しているかなり大規模なプロジェクトの一部です。この例をコンパイルしましたが、名前空間を削除することは実行可能な長期的な解決策ではありません。

4

1 に答える 1

3

お気づきのように、SWIG がヘッダー ファイルを処理するとき、デフォルトではトップレベルのヘッダー ファイルに含まれるヘッダー ファイルに再帰しないため、%include "common.h"特にその定義を SWIG に公開する必要があります。

またusing、ヘッダー ファイルでステートメントを使用することは、すべてを 1 つの名前空間にインポートするため、不適切な方法です。この場合、SWIG を混乱させます。using.cppステートメントを含むヘッダーを含むファイルは、そのグローバル名前空間を強制的に汚染します。ヘッダーは名前空間を尊重し、それらを完全に指定し、usingステートメントを.cppファイルに残す必要があります。

「名前空間の使用」をヘッダー ファイルにインクルードするのはなぜ C++ で悪い考えなのかを参照してください。

于 2013-05-12T00:24:01.133 に答える