3

I am trying to wrap a c++ library with cython. The library was compiled with Visual studio 2008, similar to my python. I use python 2.7.9 on Windows 7, 64 bit with cython 0.22.

My problem is that I always get a few

LNK2019: unresolved external symbol "...

errors.

As an illustration I used the rectangle example. I first create a testLib.lib from the Rectangle.h and the rectangle.cpp with visual studio, and then try to wrap that with cython. Here are all the files.

Rectangle.h

namespace shapes {
class Rectangle {
    public:
        int x0, y0, x1, y1;
        Rectangle(int x0, int y0, int x1, int y1);
        ~Rectangle();
        int getLength();
};
} 

rectangle.cpp

#include "Rectangle.h"

using namespace shapes;

Rectangle::Rectangle(int X0, int Y0, int X1, int Y1)
{
x0 = X0;
y0 = Y0;
x1 = X1;
y1 = Y1;
}

Rectangle::~Rectangle()
{
}

int Rectangle::getLength()
{
    return (x1 - x0);
}

I compile the above two files with Visual studo 2008 to testLib.lib. To wrap this testLib I use the following files:

pyRectangle.pyx

cdef extern from "Rectangle.h" namespace "shapes":
    cdef cppclass Rectangle:
        Rectangle(int, int, int, int)
        int x0, y0, x1, y1
        int getLength()

cdef class PyRectangle:
    cdef Rectangle *thisptr      # hold a C++ instance which we're wrapping
    def __cinit__(self, int x0, int y0, int x1, int y1):
        self.thisptr = new Rectangle(x0, y0, x1, y1)
    def __dealloc__(self):
        del self.thisptr
    def getLength(self):
        return self.thisptr.getLength()

setup.py

try:
    from setuptools import setup
    from setuptools import Extension
except ImportError:
    from distutils.core import setup
    from distutils.extension import Extension

from Cython.Distutils import build_ext

setup(
    name = 'test',
    ext_modules=[Extension("rectangle", 
                            sources = ["pyRectangle.pyx"], 
                             include_dirs=["G:/path/to/cythonTest"],
                             libraries = ["testLib"],
                             library_dirs = ["G:/path/to/cythonTest/testLib/Release"],
                            language="c++",)],
    cmdclass = {'build_ext': build_ext},
)

Now I run

python setup.py build_ext --inplace

and get the following errors

pyRectangle.obj : warning LNK4197: export 'initrectangle' specified multiple times; using first specification

Creating library build\temp.win-amd64-2.7\Release\rectangle.lib and object build\temp.win-amd64-2.7\Release\rectangle.exp

pyRectangle.obj : error LNK2019: unresolved external symbol "public: cdecl shapes::Rectangle::Rectangle(int,int,int,int)" (??0Rectangle@shapes@@QEAA@HHHH@Z) referenced in function "int __cdecl __pyx_pf_9rectangle_11PyRectangle___cinit(struct pyx_obj_9rectangle_PyRectangle *,int,int,int,int)" (?__pyx_pf_9rectangle_11PyRectangle___cinit@@YAHPEAU__pyx_obj_9rectangle_PyRectangle@@HHHH@Z)

pyRectangle.obj : error LNK2019: unresolved external symbol "public: cdecl shapes::Rectangle::~Rectangle(void)" (??1Rectangle@shapes@@QEAA@XZ) referenced in function "void __cdecl __pyx_pf_9rectangle_11PyRectangle_2__dealloc(struct pyx_obj_9rectangle_PyRectangle *)" (?__pyx_pf_9rectangle_11PyRectangle_2__dealloc@@YAXPEAU__pyx_obj_9rectangle_PyRectangle@@@Z)

pyRectangle.obj : error LNK2019: unresolved external symbol "public: int __cdecl shapes::Rectangle::getLength(void)" (?getLength@Rectangle@shapes@@QEAAHXZ) referenced in function "struct _object * __cdecl __pyx_pf_9rectangle_11PyRectangle_4getLength(struct __pyx_obj_9rectangle_PyRectangle *)" (?__pyx_pf_9rectangle_11PyRectangle_4getLength@@YAPEAU_object@@PEAU__pyx_obj_9rectangle_PyRectangle@@@Z)

I think my problem is similar to the ticket http://trac.cython.org/ticket/106, but that was marked solved for cython version 0.14, so should actually not be a problem anymore.

If I do not make a library first, but use the cpp file itself in cython, I have no issues, but in the real world with larger projects I want to simply wrap the library.

Any ideas what can be wrong?

Nora
  • 31
  • 3

0 Answers0