我有一堆C代码,我想使用Python的unittest库(在Windows中)进行单元测试,但我正在尝试找出连接C代码的最佳方法,以便Python可以执行它(和得到结果).有没有人以最简单的方式做到这一点?
一些想法包括:
这样做有规范的方法吗?我将使用不同的C模块进行相当多的操作,所以我想找到一种最省力的方法.
我已经尝试了几周让Microsoft Visual Studio 2010为我创建一个带有SWIG的DLL.如果您已经完成了这个过程,那么您是否愿意提供一个深思熟虑的逐步流程解释?我在网上到处寻找并花了很多时间试图这样做; 但是我发现的所有教程都已过时或解释不清楚.
我成功地用cygwin完成了这个过程; 但正如你们中的一些人所知,cygwin DLL并不是很实用.
因此,我知道.i,.cpp和.h文件可以一起创建DLL.我只需要知道如何使用Visual Studio C++ 2010执行此操作.我所针对的语言是Python.
请不要将我介绍给其他网站; 因为很有可能我已经去过那里并试过了.此外,请不要嗤之以鼻的评论,因为我在不久的将来让它工作非常重要.
非常感谢您的帮助!
我正在尝试使用Swig for Mac OS X编译C++扩展.但是我遇到了一些链接器错误.Python Swig的基本教程似乎也在Mac上失败了:
http://www.swig.org/Doc1.3/Python.html#Python_nn10
swig -c++ -python example.i
g++ -O2 -fPIC -c example.cxx
g++ -O2 -fPIC -c example_wrap.cxx -I/usr/include/python2.6
g++ -shared example.o example_wrap.o -o _example.so
Run Code Online (Sandbox Code Playgroud)
前三行工作正常.最后一行因链接器错误而失败.我在OS X上尝试了最后一行,并得到了同样的错误:
g++ -dynamiclib example.o example_wrap.o -o _example.so
Run Code Online (Sandbox Code Playgroud)
最后一行的错误是:
Undefined symbols for architecture x86_64:
"_PyArg_ParseTuple", referenced from:
__wrap_fact in example_wrap.o
"_PyArg_UnpackTuple", referenced from:
_SwigPyObject_own in example_wrap.o
"_PyBool_FromLong", referenced from:
_SwigPyObject_richcompare in example_wrap.o
_SwigPyObject_own in example_wrap.o
...
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
谢谢.
我有一个混合Python和C的OpenCV项目.在更改为OpenCV 2.1后,我对C代码的调用不再起作用,可能是因为OpenCV不再使用SWIG绑定.
从Python,我习惯用以下原型调用C函数:
int fast_support_transform(CvMat * I, CvMat * N,...);
Run Code Online (Sandbox Code Playgroud)
现在,我收到以下错误:
TypeError: in method 'fast_support_transform', argument 1 of type 'CvMat *'
Run Code Online (Sandbox Code Playgroud)
C代码来自我创建的库,它使用SWIG生成Python接口.我不确定,但我认为OpenCV现在正在使用ctypes,而且这段代码无法向我的本机代码发送CvMat指针.
你知道快速解决这个问题吗?欢迎任何提示.
更新:访客,注意这个问题已经过时了.OpenCV中的Python支持现在非常成熟.CvMat现在默认表示为Numpy数组.
我正在寻找一种简单的方法将C++类实例暴露给python嵌入式解释器.
我想将我的C++世界Foo实例暴露给python世界(并被视为Foo类).
这是可能的,如果是这样,怎么样?
我认为这几乎就像在第一个答案中: boost :: python :: ptr或PyInstance_New用法
我想这意味着我应该boost.Python用来包装我的图书馆?
我唯一的目标是在嵌入式python解释器中操作我的Coo Coo实例(不确定它是否可以使用前面的方法完成).
希望我很清楚,谢谢你的帮助.
更新
谢谢你的回答.事实上,我已经将我的Foo类暴露给python(使用swig).
是)我有的:
我的Foo课程:
class Foo{...};
Run Code Online (Sandbox Code Playgroud)
我的包装库(包括Foo类)暴露给python:所以我可以启动python解释器并执行以下操作:
import my_module
foo=my_modulde.Foo()
Run Code Online (Sandbox Code Playgroud)
我想要的是:
有一个C++主程序嵌入python解释器并操纵C++世界变量.
int main(int argc, char **argv)
{
Foo foo; // instanciates foo
Py_Initialize();
Py_Main(argc, argv); // starts the python interpreter
// and manipulates THE foo instance in it
Py_Finalize();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在更清楚了吗?:)
有没有人在那里使用带有C#的SWIG库?如果你有,你找到了什么陷阱以及使用该库的最佳方式是什么?我正在考虑将它用作用C编写的程序的包装器,我想将头文件包装在我可以在我的.NET应用程序中使用它们.
编辑:对目标操作系统的一些澄清.我计划在Linux和Windows上运行应用程序,因此我正在研究SWIG.P/Invoke不是一个选项.
我试图使用swig为某些C++代码创建python绑定.我似乎遇到了一个问题,试图从一些访问器函数创建python属性我有如下方法:
class Player {
public:
void entity(Entity* entity);
Entity* entity() const;
};
Run Code Online (Sandbox Code Playgroud)
我尝试使用python属性函数创建一个属性,但似乎swig生成的包装类与它至少对于setter不兼容.
你如何使用swig创建属性?
我正在使用distutils从我的项目中创建一个rpm.我有这个目录树:
project/
my_module/
data/file.dat
my_module1.py
my_module2.py
src/
header1.h
header2.h
ext_module1.cpp
ext_module2.cpp
swig_module.i
setup.py
MANIFEST.in
MANIFEST
Run Code Online (Sandbox Code Playgroud)
我的setup.py:
from distutils.core import setup, Extension
module1 = Extension('my_module._module',
sources=['src/ext_module1.cpp',
'src/ext_module2.cpp',
'src/swig_module.i'],
swig_opts=['-c++', '-py3'],
include_dirs=[...],
runtime_library_dirs=[...],
libraries=[...],
extra_compile_args=['-Wno-write-strings'])
setup( name = 'my_module',
version = '0.6',
author = 'microo8',
author_email = 'magyarvladimir@gmail.com',
description = '',
license = 'GPLv3',
url = '',
platforms = ['x86_64'],
ext_modules = [module1],
packages = ['my_module'],
package_dir = {'my_module': 'my_module'},
package_data = {'my_module': ['data/*.dat']} )
Run Code Online (Sandbox Code Playgroud)
我的MANIFEST.in档案:
include src/header1.h …Run Code Online (Sandbox Code Playgroud) 我使用SWIG来包装我的c ++类.一些方法有const std::string&一个参数.SWIG创建一个名为SWIGTYPE_p_std__string但是在调用c#中的方法时不能只传递普通字符串的类型.以下示例仅是SWIG包附带的修改示例:
public void setName(SWIGTYPE_p_std__string name)
{
examplePINVOKE.Shape_setName(swigCPtr, SWIGTYPE_p_std__string.getCPtr(name));
if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve();
}
Run Code Online (Sandbox Code Playgroud)
在我的界面文件中我只有:
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"
Run Code Online (Sandbox Code Playgroud)
并且用C++包装的方法是:
void Shape::setName(const std::string& name)
{
mName = name;
}
Run Code Online (Sandbox Code Playgroud)
我必须在接口文件中放入某种类型的地图吗?如果是这样,我该怎么做?
所以我有下一个C++代码:
#ifdef WIN32
# undef CALLBACK
# define CALLBACK __stdcall
#else
# define CALLBACK
#endif
#include <iostream>
#include <vector>
namespace OdeProxy {
typedef std::vector< double > state_type;
typedef void (CALLBACK *System)( const state_type &, state_type &, const double);
typedef void (CALLBACK *Observer)( const state_type &, double);
class Ode {
public:
state_type initialConditions;
System system;
Observer observer;
double from;
double to;
double step;
};
}
Run Code Online (Sandbox Code Playgroud)
和.i文件:
/* File : MyProject.i */
%module MyProject
%{
#include "C++/OdeProxy.h"
%}
%include "std_vector.i"
%include "C++/OdeProxy.h" …Run Code Online (Sandbox Code Playgroud)