Reputation: 43
I'm trying to take advantage of some C++ functions by calling them from Python. To do that, I was trying to construct a small demo function to show myself how python types are converted to C++ types. According to the Pybind11 documentation, if you include pybind11/stl.h
in your header, automatic conversion should take place for many common types:
https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html
What is wrong with the following code?
my.cpp
#include <vector>
int add_these(std::vector<int> &v) {
int sum=0;
for (int i = 0; i < v.size(); ++i) {
sum += v[i];
}
return sum;
}
wrap.cpp
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <vector>
#include "my.cpp"
namespace py=pybind11;
PYBIND11_MODULE(python_example, m) {
m.def("addup", &add_these);
#ifdef VERSION_INFO
m.attr("__version__") = VERSION_INFO;
#else
m.attr("__version__") = "dev";
#endif
}
I have successfully compiled other demos that I've built, so I don't think it's an error in my compiling process. But compiling this demo I get this error:
wrap.cpp
creating C:\Users\scottjr1\AppData\Local\Temp\pip-req-build-wyi5ezw1\build\lib.win-amd64-3.7
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:c:\users\scottjr1\appdata\python\python37\libs /LIBPATH:c:\users\scottjr1\appdata\python\python37\PCbuild\amd64 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\ATLMFC\lib\x64" "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\lib\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\lib\um\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\ucrt\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64" /EXPORT:PyInit_python_example build\temp.win-amd64-3.7\Release\src/my.obj build\temp.win-amd64-3.7\Release\src/wrap.obj /OUT:build\lib.win-amd64-3.7\python_example.cp37-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.7\Release\src\python_example.cp37-win_amd64.lib
wrap.obj : error LNK2005: "int __cdecl add_these(class std::vector<int,class std::allocator<int> > &)" (?add_these@@YAHAEAV?$vector@HV?$allocator@H@std@@@std@@@Z) already defined in my.obj
Creating library build\temp.win-amd64-3.7\Release\src\python_example.cp37-win_amd64.lib and object build\temp.win-amd64-3.7\Release\src\python_example.cp37-win_amd64.exp
build\lib.win-amd64-3.7\python_example.cp37-win_amd64.pyd : fatal error LNK1169: one or more multiply defined symbols found
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\VC\\Tools\\MSVC\\14.16.27023\\bin\\HostX86\\x64\\link.exe' failed with exit status 1169
Upvotes: 3
Views: 1041
Reputation: 275395
#include "my.cpp"
is wrong. Replace with #include "my.h"
.
my.h
should contain:
#include <vector>
int add_these(std::vector<int> const &v);
the declaration of your function.
and my.cpp
should contain the definition:
#include "my.h"
int add_these(std::vector<int> const&v) {
int sum=0;
for (int i = 0; i < v.size(); ++i) {
sum += v[i];
}
return sum;
}
the error you are seeing is that you have two .cpp
files that contain the definition of the function; that is not allowed in C++.
#include "my.cpp"
copy pastes the content of my.cpp
where the include directive is. This is not the same as import in python.
This didn't occur in other cases probably because you didn't link the cpp file; regardless including cpp files breaks convention, don't do it.
Upvotes: 0
Reputation: 43
The problem was simple: header guards don't work on .cpp files so the solution was to break up my.cpp into my.hpp and my.cpp files and include the my.hpp file in the wrap.cpp file.
Of the few demos I've done, this was only required for this demo so far. I'm not sure why breaking up the file is necessary for this demo but not others where I've included the .cpp files directly.
Upvotes: 1