LINUX.ORG.RU

Wrapper над С++ для Python3

 , ,


1

1

Прошу помощи в построении обертки для С++ кода и ее сборки с целью использования в Python3 скрипте.

Изложение моей попытки прилагается.

Имеется C++ класс Image:

$ cat image.h 
#include <opencv2/opencv.hpp>

class Image {
public:
    Image();
    int getWidth(cv::Mat);
    ~Image();
};

$ cat image.cpp 
#include "image.h"

Image::Image(){}
Image::~Image(){}
int Image::getWidth(cv::Mat img){return img.size().width;}

Для него создана Си обертка:

$ cat wrapper.cpp
#include <new>
#include "image.h"

extern "C" {

    void * createImage(void) {
        return new Image;
    }

    void deleteImage(void *ptr) {
        delete ptr;
    }

    bool getWidth(void *ptr, cv::Mat img){
	Image * ref = reinterpret_cast<Image*>(ptr);
        return ref->getWidth(img);
    }

}

Python3 скрипт имеет вид:

#!/usr/bin/python3
import cv2

from ctypes import cdll
cpplib = cdll.LoadLibrary('./wrapper.so')
filename="test.png"
img = cv2.imread(filename)
print(cpplib.getWidth(img))

Ну и наконец, правила сборки

wrapper.so: wrapper.o
	gcc -shared -o $@ $<

wrapper.o: wrapper.cpp image.o
	g++ -Wall -fPIC -O2 -c -o $@ $^  -lopencv_core

image.o: image.cpp
	g++ -Wall -fPIC -O2 -o $@ -c $<

Попытка запуска питоноского скрипта

./test.py 
Traceback (most recent call last):
  File "./test.py", line 5, in <module>
    cpplib = cdll.LoadLibrary('./wrapper.so')
  File "/usr/lib/python3.6/ctypes/__init__.py", line 426, in LoadLibrary
    return self._dlltype(name)
  File "/usr/lib/python3.6/ctypes/__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: ./wrapper.so: undefined symbol: _ZTVN10__cxxabiv117__class_type_infoE

cffi, не? Оно заметно попроще для применения.

lu4nik ★★★
()
Ответ на: комментарий от dyb4hzvo

Сходу скажу что надо кастовать void* к Image* когда вызываешь delete.

закостовал

ну и следующие правила сборки решили проблему (пока не понял почему)

$ cat Makefile 
wrapper.so: wrapper.cpp libimage.so
	gcc -shared -fPIC -o $@ $&lt; -L. -limage

libimage.so: image.cpp image.h
	g++ -shared -fPIC -o $@ $&lt;  -lopencv_core

doubletensor
() автор топика
wrapper.so: wrapper.o
	gcc -shared -o $@ $<

wrapper.o: wrapper.cpp image.o
	g++ -Wall -fPIC -O2 -c -o $@ $^  -lopencv_core

image.o точно там, где нужно? Кажется, что его надо перенести в первую цель. Иначе он в библиотеку не попадает, видимо.

xaizek ★★★★★
()
wrapper.so: wrapper.o
	gcc -shared -o $@ $<

wrapper.o: wrapper.cpp image.o
	g++ -Wall -fPIC -O2 -c -o $@ $^  -lopencv_core

image.o: image.cpp
	g++ -Wall -fPIC -O2 -o $@ -c $<

Дичь какая, курите разницу между компиляцией и линковкой.

  • wrapper.cpp должен собираться также как image.cpp
  • opencv нужно линковать к библиотеке
  • c++ код нужно линковать g++.
slovazap ★★★★★
()
Ответ на: комментарий от doubletensor

Ну так SWIG он для биндингов к C++ и. Почитай внимательно что это и как этим пользуются.

Dark_SavanT ★★★★★
()

еще можно boost::python или pybind заюзать

samson ★★
()

Зачем это все, если можно сделать это из Python?

filename = "test.png"
img = cv2.imread(filename)
height, width, _ = img.shape
print(width)
theLastOfCats
()

Вместо SWIG лучше pybind11 использовать, он существенно проще

Sahas ★★★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.