模板包装上的 SWIG 错误

Posted

技术标签:

【中文标题】模板包装上的 SWIG 错误【英文标题】:SWIG error on template wrapping 【发布时间】:2017-10-08 13:32:51 【问题描述】:

我正在尝试使用 SWIG 在 python 中包装一段代码。以下是接口文件:

/* dnn_face_embedding_extractor.ii */
%module dnn_face_embedding_extractor
%
/* Put header files here or function declarations like below */
extern template <template <int,template<typename>class,int,typename> class      block, int N, template<typename>class BN, typename SUBNET>;
extern template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>;
extern template <int N, template <typename> class BN, int stride, typename SUBNET> ;
extern std::vector<matrix<float,0,1>> am_main(char* image_name);
%

%template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
%template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
%template <int N, template <typename> class BN, int stride, typename SUBNET> ;
extern std::vector<matrix<float,0,1>> am_main(char* image_name);

我遇到以下错误: dnn_face_embedding_extractor.ii:11:错误:输入(1)中的语法错误。 谁能帮帮我?

附:我想包装下面的代码,它没有错误,我可以编译它。同样值得注意的是,代码的灵感来自于 Dlib 中的一个示例。

#include <dlib/dnn.h>
#include <dlib/gui_widgets.h>
#include <dlib/clustering.h>
#include <dlib/string.h>
#include <dlib/image_io.h>
#include <dlib/image_processing/frontal_face_detector.h>
using namespace dlib;
using namespace std;

template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual = add_prev1<block<N,BN,1,tag1<SUBNET>>>;

template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual_down = add_prev2<avg_pool<2,2,2,2,skip1<tag2<block<N,BN,2,tag1<SUBNET>>>>>>;

template <int N, template <typename> class BN, int stride, typename SUBNET> 
using block  = BN<con<N,3,3,1,1,relu<BN<con<N,3,3,stride,stride,SUBNET>>>>>;

template <int N, typename SUBNET> using ares      = relu<residual<block,N,affine,SUBNET>>;
template <int N, typename SUBNET> using ares_down = relu<residual_down<block,N,affine,SUBNET>>;

template <typename SUBNET> using alevel0 = ares_down<256,SUBNET>;
template <typename SUBNET> using alevel1 = ares<256,ares<256,ares_down<256,SUBNET>>>;
template <typename SUBNET> using alevel2 = ares<128,ares<128,ares_down<128,SUBNET>>>;
template <typename SUBNET> using alevel3 = ares<64,ares<64,ares<64,ares_down<64,SUBNET>>>>;
template <typename SUBNET> using alevel4 = ares<32,ares<32,ares<32,SUBNET>>>;

using anet_type = loss_metric<fc_no_bias<128,avg_pool_everything<
                        alevel0<
                        alevel1<
                        alevel2<
                        alevel3<
                        alevel4<
                        max_pool<3,3,2,2,relu<affine<con<32,7,7,2,2,
                        input_rgb_image_sized<150>
                        >>>>>>>>>>>>;

std::vector<matrix<float,0,1>> am_main(char* image_name) try
    // The first thing we are going to do is load all our models.  First, since we need to
    // find faces in the image we will need a face detector:
frontal_face_detector detector = get_frontal_face_detector();
    // We will also use a face landmarking model to align faces to a standard pose:  (see face_landmark_detection_ex.cpp for an introduction)
    shape_predictor sp;
    deserialize("shape_predictor_5_face_landmarks.dat") >> sp;
    // And finally we load the DNN responsible for face recognition.
    anet_type net;
    deserialize("dlib_face_recognition_resnet_model_v1.dat") >> net;

    matrix<rgb_pixel> img;
    load_image(img, image_name);

    // Run the face detector on the image of our action heroes, and for each face extract a
    // copy that has been normalized to 150x150 pixels in size and appropriately rotated
    // and centered.
    std::vector<matrix<rgb_pixel>> faces;
    for (auto face : detector(img))
    
        auto shape = sp(img, face);
        matrix<rgb_pixel> face_chip;
        extract_image_chip(img, get_face_chip_details(shape,150,0.25), face_chip);
        faces.push_back(move(face_chip));
    

    if (faces.size() == 0)
    
        cout << "No faces found in image!" << endl;
        std::vector<matrix<float,0,1>> face_descriptors;
        return face_descriptors;
    

    // This call asks the DNN to convert each face image in faces into a 128D vector.
    // In this 128D vector space, images from the same person will be close to each other
    // but vectors from different people will be far apart.  So we can use these vectors to
    // identify if a pair of images are from the same person or from different people.  
    std::vector<matrix<float,0,1>> face_descriptors = net(faces);
    return face_descriptors;
    // return 0;

catch (std::exception& e)

    cout << e.what() << endl;

int main(int argc, char** argv) 
    return 0;

【问题讨论】:

你的 C++ 甚至不合法,例如extern template &lt;int N, template &lt;typename&gt; class BN, int stride, typename SUBNET&gt; ; 缺少变量声明或函数声明或类定义/声明之类的东西,甚至是合法的。我实际上无法从您在这里展示的内容中弄清楚您的 C++ 接口做了什么,这是回答如何使其与 SWIG 一起工作的先决条件。你能做一个最小的、完整的例子来展示(至少用最少的有效 C++)模板是如何工作的吗? 我刚刚添加了 C++ 代码。谢谢。 【参考方案1】:

请查看http://www.swig.org/Doc3.0/SWIGDocumentation.html#SWIGPlus_nn30 的 Swig 文档,第 6.18 节模板。您需要在接口文件中实例化模板,解析器希望在第 11 行进行实例化。尝试类似:

%template (MyStdVector) std::vector<matrix<float,0,1> >;

其他模板也类似。

【讨论】:

以上是关于模板包装上的 SWIG 错误的主要内容,如果未能解决你的问题,请参考以下文章

swig -c++ 选项破坏纯 C 文件的包装,错误 C3861:unresolved externals

编译 SWIG 输出的包装器模块时出现 6 个错误?

SWIG tcl:log4cpp 包装器的未定义符号错误

使用 SWIG 构建错误

Python 错误:在 SWIG 生成的 C++ 模板代码模块中未定义构造函数

如何使用 SWIG 在 C++ API 上生成 C 包装器? [复制]