- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个饱受困扰的C++类容器MyContainer,其中包含MyObject类型的对象,也是C++类。
以下是C++头代码(freemenot.h)
#ifndef freemenotH
#define freemenotH
#include <vector>
#include <string>
using std::string;
class MyObject
{
public:
MyObject(const string& lbl);
~MyObject();
string getLabel();
private:
string label;
};
class MyContainer
{
public:
MyContainer();
~MyContainer();
void addObject(MyObject* o);
MyObject* getObject(unsigned int t);
int getNrOfObjects();
private:
std::vector<MyObject*> mObjects;
};
#endif
#include "freemenot.h"
#include <iostream>
using namespace std;
/* MyObject source */
MyObject::MyObject(const string& lbl)
:
label(lbl)
{ cout<<"In object ctor"<<endl; }
MyObject::~MyObject() { cout<<"In object dtor"<<endl; }
string MyObject::getLabel() { return label; }
/* MyContainer source */
MyContainer::MyContainer() { cout<<"In container ctor"<<endl; }
MyContainer::~MyContainer()
{
cout<<"In container dtor"<<endl;
for(unsigned int i = 0; i < mObjects.size(); i++)
{
delete mObjects[i];
}
}
int MyContainer::getNrOfObjects() { return mObjects.size(); }
void MyContainer::addObject(MyObject* o) { mObjects.push_back(o); }
MyObject* MyContainer::getObject(unsigned int i) { return mObjects[i]; }
MyContainer* getAContainerWithSomeObjects()
{
MyContainer* c = new MyContainer();
MyObject* o1 = new MyObject();
c.add(o1);
return c;
}
%module freemenot
%{ #include "freemenot.h" %}
%include "std_string.i"
//Expose to Python
%include "freemenot.h"
cmake_minimum_required(VERSION 2.8)
project(freemenot)
find_package(SWIG REQUIRED)
include(UseSWIG)
find_package(PythonInterp)
find_package(PythonLibs)
get_filename_component(PYTHON_LIB_FOLDER ${PYTHON_LIBRARIES} DIRECTORY CACHE)
message("Python lib folder: " ${PYTHON_LIB_FOLDER})
message("Python include folder: " ${PYTHON_INCLUDE_DIRS})
message("Python libraries: " ${PYTHON_LIBRARIES})
set(PyModule "freemenot")
include_directories(
${PYTHON_INCLUDE_PATH}
${CMAKE_CURRENT_SOURCE_DIR}
)
link_directories( ${PYTHON_LIB_FOLDER})
set(CMAKE_MODULE_LINKER_FLAGS ${CMAKE_CURRENT_SOURCE_DIR}/${PyModule}.def)
set_source_files_properties(${PyModule}.i PROPERTIES CPLUSPLUS ON)
set_source_files_properties(${PyModule}.i PROPERTIES SWIG_FLAGS "-threads")
SWIG_ADD_LIBRARY(${PyModule}
MODULE LANGUAGE python
SOURCES ${PyModule}.i freemenot.cpp)
SWIG_LINK_LIBRARIES (${PyModule} ${PYTHON_LIB_FOLDER}/Python37_CG.lib )
# INSTALL PYTHON BINDINGS
# Get the python site packages directory by invoking python
execute_process(COMMAND python -c "import site; print(site.getsitepackages()[0])" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
message("PYTHON_SITE_PACKAGES = ${PYTHON_SITE_PACKAGES}")
install(
TARGETS _${PyModule}
DESTINATION ${PYTHON_SITE_PACKAGES})
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PyModule}.py
DESTINATION ${PYTHON_SITE_PACKAGES}
)
import freemenot as fmn
def getContainer():
c = fmn.MyContainer()
o1 = fmn.MyObject("This is a label")
o1.thisown = 0
c.addObject(o1)
return c
c = getContainer()
print (c.getNrOfObjects())
#if the thisown flag for objects in the getContainer function
#is equal to 1, the following call return an undefined object
#If the flag is equal to 0, the following call will return a valid object
a = c.getObject(0)
print (a.getLabel())
最佳答案
您可以通过多种方法来解决此问题,因此,在此过程中,我将依次尝试解释每种方法。希望这对于了解SWIG的选项和内幕很有用,即使您只真正需要第一个示例。
添加Python代码直接修改thisown
最像您建议的解决方案依赖于使用SWIG的%pythonprepend
指令添加一些额外的Python代码。您可以根据您关心的重载的C++声明来定位它,例如:
%module freemenot
%{ #include "freemenot.h" %}
%include "std_string.i"
%pythonprepend MyContainer::addObject(MyObject*) %{
# mess with thisown
print('thisown was: %d' % args[0].thisown)
args[0].thisown = 0
%}
//Expose to Python
%include "freemenot.h"
*args
而不是命名参数传入参数的事实,因此我们必须通过位置号进行访问。
-builtin
),并且猴子修补也是一种选择。
thisown
MyObject *
的
o
的函数。 (这里最简单的解决方案是使名称在头文件中描述预期的语义,如果这可能当前不匹配的话,这具有使IDE和文档更加清晰的副作用)。
%module freemenot
%{ #include "freemenot.h" %}
%include "std_string.i"
%typemap(in) MyObject *o {
PyObject_SetAttrString($input, "thisown", PyInt_FromLong(0)); // As above, but C API
$typemap(in,MyObject*); // use the default typemap
}
//Expose to Python
%include "freemenot.h"
$typemap
来“粘贴”另一种类型映射,特别是将
MyObject*
的默认类型粘贴到我们自己的类型映射中。值得一看的是在生成的包装器文件内部之前/之后的示例,以了解最终的外观。
SwigPyObject
结构的
own
成员
setattr
进行编码,因此我们可以使该类型映射适应于SWIG的更多内部功能,并跳过从C到Python的往返过程,并再次返回到C。
PyObject*
转换为
SwigPyObject*
,但这将需要我们自己编写错误处理/类型检查(此PyObject甚至是SWIG吗?),并依赖于SWIG可以生成Python接口(interface)的各种不同方式的细节。相反,我们可以调用一个函数来为我们处理所有这些,因此我们现在可以像这样编写我们的类型图:
%module freemenot
%{ #include "freemenot.h" %}
%include "std_string.i"
%typemap(in) MyObject *o {
// TODO: handle NULL pointer still
SWIG_Python_GetSwigThis($input)->own = 0; // Safely cast $input from PyObject* to SwigPyObject*
$typemap(in,MyObject*); // use the default typemap
}
//Expose to Python
%include "freemenot.h"
MyContainer
假定它可以始终在存储的每个实例上调用
delete
(因此拥有这些语义)。
MyObject *getInstanceOfThing() {
static MyObject a;
return &a;
}
thisown
设置为0,但是这里它本来应该是0,所以当容器被释放时,我们仍然不能合法地在指针上调用
delete
。
MyObject
是可复制构造的,那么您可以简单地创建一个新实例,并确保无论它来自何处,对于容器而言都是合法的删除它。我们可以通过稍微调整一下typemap来做到这一点:
%module freemenot
%{ #include "freemenot.h" %}
%include "std_string.i"
%typemap(in) MyObject *o {
$typemap(in,MyObject*); // use the default typemap as before
$1 = new $*1_type(*$1); // but afterwards call copy-ctor
}
//Expose to Python
%include "freemenot.h"
$*1_type
是一次取消引用的typemap参数的类型。我们可能只是在这里编写了
MyObject
,因为它可以解决这个问题,但是如果您的容器确实是模板,那么它可以让您处理诸如模板之类的事情,或者使用
%apply
在其他类似容器中重用typemap。
thisown
,则该泄漏是在假设容器将拥有现在不再拥有的所有权的前提下发生的。
Py_INCREF
并保留对基础
PyObject*
的引用,无论它来自何处。如果在销毁时获得回调,则还可以调用
Py_DECREF
并强制Python运行时将对象保持与容器一样长的时间。
MyObject*
/
PyObject*
配对保持 Activity 的情况下,也可以通过使影子容器保持 Activity 的状态来保持这种状态。除非您愿意将另一个对象添加到容器中,或者将其子类化,或者可以非常确定容器的初始Python实例将始终存在足够长的时间,否则这很难做到。
关于python - 添加swig pythoncode以在Python对象上设置thisown标志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50259152/
我有两个维度 DimFlag 和 DimPNL 以及一个事实表 FactAmount 。我正在寻找:当 pnl 是 stat(Is Stat=1) 时:sum (Actual x FlagId)对于
我试图弄清楚登录模块标志在 JAAS 中是如何工作的(使用 JBoss 5.1 EAP),我遇到了一个令人费解的情况,我希望有人能为我澄清一下。 对于背景,我的 login-config.xml 如下
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
我正在通过 gradle 使用 doclet 运行 javadoc,当我运行 javadoc/doclet 任务时,我收到下一个错误: error - invalid flag: -doctitle
我尝试使用sqoop --where标志将特定的行从MySQL表导入到HDFS,但是结果不符合预期。 命令: sqoop import \ --connect "jdbc:mysql://XXXX
我有一个语言面板,其中有一个图像 (main-image),显示页面加载时的情况。我还有三个额外的图像,它们在页面加载时隐藏。 问题是当点击附加图像之一时如何切换主图像。我需要使用单击的 image
奇怪...在 StackOverflow 上有很多关于此 attr 的问题,但没有人回答我的以下问题: 我有一个span(仅作为示例),其中启用了ContentEditable。我只想保存更改的元素(
我正在使用 ChartJS 2.0 在 UI 上绘制图表。而且我能够呈现饼图。但我希望鼠标悬停时显示数据以及“%”符号。我如何追加 % 因此,如果在鼠标悬停时我得到 Rented: 93 我想看到 R
我使用的是 Servlet 3.0,我想用 HttpOnly 标志保护我的 cookie。我的 web.xml 是 true
我有一个简单的服务: public class TestService extends Service { final String LOG_TAG = "myLogs"; public void o
我正在尝试将 wget 与包含“#”符号的 url 一起使用。无论我做什么来逃避这个角色,它都不起作用。我用过\、' 和 "。但它们都不起作用。有人有什么建议吗? 谢谢! 最佳答案 如果您真的想让它有
我正在尝试创建一个数据库,但我不知道如何转义数据库名称中的 - 符号。 mysql> create database happy-face; 给我一个错误 mysql> create databa
我为我的计算机科学类(class)编写了一个程序,它读取一个文件并导入数据,然后只添加数字,但它似乎添加了一个额外的加号。 import java.io.*; //necessary for File
可能是个愚蠢的问题,但我怎样才能在与某些文本看到图像相同的行中获取图像(在本例中为标志)? 到目前为止我的 HTML 代码: FRA 最佳答案 试试这个: img { height:20px
我需要一些有关 clone() 系统调用的帮助。我试图将它与标志 CLONE_CHILD_CLEARTID 一起使用,但我看不到我指定为参数的字段值有任何变化。这是一个简单的代码: int the_c
查看 mySQL 转储时,我遇到了一些东西,想知道它们是什么。 我明白了: /*!50001 DROP TABLE IF EXISTS `xxx` */; flag 50001是什么意思,有什么意思的
是否可以传递任何 Java 编译器标志来告诉编译器不允许使用原始类型?也就是说,对于任何泛型类,让编译器强制使用参数化版本,否则抛出编译错误? 最佳答案 JDK7 (b38) 介绍 -Xlint:ra
[Flags] public enum MyEnum { None = 0, Setting1 = (1 GetAllEnums() where T : struct
我正在浏览 PackageManager API。我发现定义了以下常量: 1) GET_DISABLED_COMPONENTS 2) GET_DISABLED_UNTIL_USED_COMPONENT
我编写了一个 Go 程序来模拟按键操作。为此,我必须使用 cgo 和不同的 C 代码片段,具体取决于正在编译 Go 代码的操作系统。我编写的代码如下所示: package keyboard /* #i
我是一名优秀的程序员,十分优秀!