05.11., 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Various improvements of the SWIG Lua bindings:

* Added DISOWN typemaps to various functions, where CAMPVis takes ownership of passed pointers. This prevents the Lua garbage collector from deleting those items.
* Improved sigslot bindings to also support pass-by-value signal arguments.
* Changed import type of campvis.i from #include to #import

refs #643
parent 12f36262
......@@ -5,14 +5,14 @@
%include std_string.i
%include std_vector.i
%include "core/bindings/campvis.i"
%import "core/bindings/campvis.i"
%{
#include "application/campvisapplication.h"
//#include "core/properties/allproperties.h"
//#include "core/pipeline/abstractprocessor.h"
//#include "core/pipeline/abstractworkflow.h"
//#include "core/pipeline/autoevaluationpipeline.h"
#include "core/properties/allproperties.h"
#include "core/pipeline/abstractprocessor.h"
#include "core/pipeline/abstractworkflow.h"
#include "core/pipeline/autoevaluationpipeline.h"
%}
namespace campvis {
......@@ -26,8 +26,10 @@ namespace campvis {
void deinit();
int run();
%apply SWIGTYPE *DISOWN {AbstractPipeline* pipeline};
void addPipeline(const std::string& name, AbstractPipeline* pipeline);
DataContainer* createAndAddDataContainer(const std::string& name);
%clear AbstractPipeline* pipeline;
void rebuildAllShadersFromFiles();
void setPipelineVisibility(AbstractPipeline* pipeline, bool visibility);
......
......@@ -89,9 +89,11 @@ namespace campvis {
connect(_btnClear, SIGNAL(clicked()), this, SLOT(clearLog()));
connect(_btnExecute, SIGNAL(clicked()), this, SLOT(execute()));
connect(_editCommand, SIGNAL(returnPressed()), this, SLOT(execute()));
connect(this, SIGNAL(s_messageAppended(QString)), this, SLOT(appendMessage(QString)));
}
void ScriptingWidget::appendMessage(const QString& message) {
void ScriptingWidget::appendMessage(QString message) {
_consoleDisplay->append(message);
}
......@@ -134,7 +136,7 @@ namespace campvis {
void ScriptingWidget::logFiltered(const std::string &cat, cgt::LogLevel level, const std::string& msg, const std::string& extendedInfo/*=""*/) {
if (level == cgt::LuaInfo || level == cgt::LuaError) {
appendMessage(QString::fromStdString(msg));
emit s_messageAppended(QString::fromStdString(msg));
}
}
......
......@@ -99,7 +99,7 @@ namespace campvis {
*
* \param message message to append to the log viewer
*/
void appendMessage(const QString& message);
void appendMessage(QString message);
private slots:
/**
......@@ -110,7 +110,8 @@ namespace campvis {
void execute();
signals:
void s_commandExecuted(const QString& cmd);
void s_commandExecuted(QString cmd);
void s_messageAppended(QString message);
private:
QTextEdit* _consoleDisplay; ///< Text edit to hold the console output
......
......@@ -58,17 +58,10 @@ local initCallback = function()
LuaDemo.image_reader.s_validated:connect(callback)
-- let us create a fancy transfer function
local geometry1 = campvis.TFGeometry1D_createQuad(cgt.vec2(0.12, 0.15), cgt.col4(85, 0, 0, 128),
cgt.col4(255, 0, 0, 128))
local geometry2 = campvis.TFGeometry1D_createQuad(cgt.vec2(.19, .28), cgt.col4(89, 89, 89, 155),
cgt.col4(89, 89, 89, 155))
local geometry3 = campvis.TFGeometry1D_createQuad(cgt.vec2(.41, .51), cgt.col4(170, 170, 128, 64),
cgt.col4(192, 192, 128, 64))
local dvrTF = campvis.Geometry1DTransferFunction(128, cgt.vec2(0, 0.05))
dvrTF:addGeometry(geometry1)
dvrTF:addGeometry(geometry2)
dvrTF:addGeometry(geometry3)
dvrTF:addGeometry(campvis.TFGeometry1D_createQuad(cgt.vec2(0.12, 0.15), cgt.col4(85, 0, 0, 128), cgt.col4(255, 0, 0, 128)))
dvrTF:addGeometry(campvis.TFGeometry1D_createQuad(cgt.vec2(.19, .28), cgt.col4(89, 89, 89, 155), cgt.col4(89, 89, 89, 155)))
dvrTF:addGeometry(campvis.TFGeometry1D_createQuad(cgt.vec2(.41, .51), cgt.col4(170, 170, 128, 64), cgt.col4(192, 192, 128, 64)))
LuaDemo.vr:getNestedProperty("RaycasterProps::TransferFunction"):replaceTF(dvrTF)
end
......
......@@ -31,16 +31,22 @@ static const char* const SOURCE_DIR = CAMPVIS_SOURCE_DIR;
// Template specialisations and instantiations required to get signals to work in Lua
namespace sigslot {
template<>
struct LuaConnectionArgTraits<campvis::AbstractProcessor*> {
static const char* const typeName;
};
struct LuaConnectionArgTraits<campvis::AbstractProcessor*> { static const char* const typeName; };
const char* const LuaConnectionArgTraits<campvis::AbstractProcessor*>::typeName = "campvis::AbstractProcessor *";
template<>
struct LuaConnectionArgTraits<campvis::DataHandle> { static const char* const typeName; };
const char* const LuaConnectionArgTraits<campvis::DataHandle>::typeName = "campvis::DataHandle *";
template<>
struct LuaConnectionArgTraits<std::string> { static const char* const typeName; };
const char* const LuaConnectionArgTraits<std::string>::typeName = "std::string *";
}
}
%template(sigslot_signal1_AbstractProcessor) sigslot::signal1<campvis::AbstractProcessor*>;
%template(sigslot_signal2_string_DataHandle) sigslot::signal2<std::string, campvis::DataHandle>;
%template(PairStringDataHandle) std::pair<std::string, campvis::DataHandle>;
%template(VectorOfPairStringDataHandle) std::vector< std::pair< std::string, campvis::DataHandle> >;
......@@ -262,7 +268,9 @@ namespace campvis {
GenericGeometryTransferFunction(const cgt::vec3& size, const cgt::vec2& intensityDomain = cgt::vec2(0.f, 1.f));
virtual ~GenericGeometryTransferFunction();
%apply SWIGTYPE *DISOWN {T* geometry};
void addGeometry(T* geometry);
%clear T* geometry;
};
/* Geometry1DTransferFunction */
......@@ -293,11 +301,13 @@ namespace campvis {
class TransferFunctionProperty : public AbstractProperty {
public:
%apply SWIGTYPE *DISOWN {AbstractTransferFunction* tf};
TransferFunctionProperty(const std::string& name, const std::string& title, AbstractTransferFunction* tf);
virtual ~TransferFunctionProperty();
AbstractTransferFunction* getTF();
void replaceTF(AbstractTransferFunction* tf);
%clear AbstractTransferFunction* tf;
};
/* IHasWorldBounds */
......@@ -327,6 +337,7 @@ namespace campvis {
/* Downcast the return value of DataHandle::getData to appropriate subclass */
%factory(const AbstractData* campvis::DataHandle::getData, const campvis::ImageData);
%apply SWIGTYPE *DISOWN {AbstractData* data};
class DataHandle {
public:
explicit DataHandle(AbstractData* data = 0);
......@@ -384,8 +395,11 @@ namespace campvis {
%immutable;
sigslot::signal0 s_changed;
sigslot::signal2<std::string, DataHandle> s_dataAdded;
%mutable;
};
%clear AbstractData* data;
/* Down casting or super classes.
* Down casting follows the order of declaration.
......@@ -439,6 +453,7 @@ namespace campvis {
%immutable;
sigslot::signal1<AbstractProcessor*> s_validated;
sigslot::signal1<AbstractProcessor*> s_invalidated;
%mutable;
};
......@@ -459,8 +474,10 @@ namespace campvis {
AbstractProcessor* getProcessor(const std::string& name) const;
AbstractProcessor* getProcessor(size_t index) const;
%immutable;
sigslot::signal0 s_init;
sigslot::signal0 s_deinit;
%mutable;
};
/* AutoEvaluationPipeline */
......@@ -494,8 +511,10 @@ namespace campvis {
int getCurrentStageId() const;
void setCurrentStage(int stage);
%immutable;
sigslot::signal2<int, int> s_stageChanged;
sigslot::signal0 s_stageAvailabilityChanged;
%mutable;
};
......@@ -509,16 +528,5 @@ namespace campvis {
}
%luacode {
function campvis.newPipeline (name, o)
if not name then
error("A name must be provided when creating a new pipeline!")
end
o = o or {} -- create object if user does not provide one
setmetatable(o, {__index = instance})
return o
end
print("Module campvis-core loaded")
}
......@@ -7,7 +7,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0 FATAL_ERROR)
MESSAGE(STATUS "Configuring sigslot Library")
# headers
SET(SIGSLOT_HEADERS sigslot.h)
SET(SIGSLOT_HEADERS sigslot.h sigslot.i)
# sources
SET(SIGSLOT_SOURCES sigslot.cpp)
......
......@@ -12,6 +12,7 @@
%{
#include <cstdio>
#include <iostream>
#include <type_traits>
#include "tbb/recursive_mutex.h"
#include "ext/cgt/logmanager.h"
#include "ext/sigslot/sigslot.h"
......@@ -42,7 +43,35 @@ namespace sigslot {
* Type bundling all information necessary to inject a signal argument into a Lua state:
* a pointer to the argument and its corresponding SWIG type information.
*/
typedef std::pair<void*, swig_type_info*> ArgWithTypeInfoType;
struct ArgWithTypeInfoType {
void* ptr;
swig_type_info* type_info;
void (*deleter)(void*);
};
template<typename T, bool makeCopy>
struct CreateAwtitHelper {};
template<typename T>
struct CreateAwtitHelper<T, true> {
static void deletePtr(void* ptr) {
delete static_cast<T*>(ptr);
}
static ArgWithTypeInfoType createAwtit(T arg, swig_type_info* typeInfo) {
ArgWithTypeInfoType toReturn = { new T(arg), typeInfo, &deletePtr };
return toReturn;
}
};
template<typename T>
struct CreateAwtitHelper<T, false> {
static ArgWithTypeInfoType createAwtit(T arg, swig_type_info* typeInfo) {
ArgWithTypeInfoType toReturn = { arg, typeInfo, nullptr };
return toReturn;
}
};
/*
* Return an object bundling the provided argument with its SWIG type information.
......@@ -56,7 +85,8 @@ namespace sigslot {
LogMgr.log("Lua", cgt::LuaError, "SWIG wrapper for " + std::string(typeName) + " not found");
}
return std::make_pair(arg, typeInfo);
ArgWithTypeInfoType toReturn = CreateAwtitHelper<T, !std::is_pointer<T>::value && !std::is_reference<T>::value>::createAwtit(arg, typeInfo);
return toReturn;
}
/*
......@@ -66,7 +96,7 @@ namespace sigslot {
inline std::list<ArgWithTypeInfoType>* argWithTypeInfoListCons(ArgWithTypeInfoType head,
std::list<ArgWithTypeInfoType>* tail)
{
if (head.second == nullptr) {
if (head.type_info == nullptr) {
delete tail;
} else if (tail != nullptr) {
tail->push_front(head);
......@@ -227,7 +257,7 @@ namespace sigslot {
swiglua_ref_get(&_slot_fn);
for (auto it = argWithTypeInfoList->begin(); it != argWithTypeInfoList->end(); ++it)
SWIG_NewPointerObj(_slot_fn.L, it->first, it->second, 0);
SWIG_NewPointerObj(_slot_fn.L, it->ptr, it->type_info, 0);
if (lua_pcall(_slot_fn.L, argWithTypeInfoList->size(), 0, 0) != LUA_OK) {
const char* errorMsg = lua_tostring(_slot_fn.L, -1);
......@@ -240,6 +270,10 @@ namespace sigslot {
lua_pop(_slot_fn.L, 1);
}
for (auto it = argWithTypeInfoList->begin(); it != argWithTypeInfoList->end(); ++it) {
if (it->deleter != nullptr)
(it->deleter)(it->ptr);
}
delete argWithTypeInfoList;
}
}
......@@ -627,6 +661,24 @@ namespace sigslot {
++it;
}
}
void disconnectAllLuaSlots() {
typedef sigslot::_signal_base2<arg1_type, arg2_type>::connections_list connections_list;
connections_list::iterator it = $self->m_connected_slots.begin();
connections_list::iterator itEnd = $self->m_connected_slots.end();
while (it != itEnd) {
sigslot::_lua_connection2<arg1_type, arg2_type>* lua_connection =
dynamic_cast<sigslot::_lua_connection2<arg1_type, arg2_type>*>(*it);
if (lua_connection != nullptr) {
delete lua_connection;
$self->m_connected_slots.erase(it);
}
++it;
}
}
}
};
......
%module base
%include std_string.i
%import "ext/cgt/bindings/cgt.i"
%include "core/bindings/campvis.i"
%import "core/bindings/campvis.i"
%{
#include "core/properties/allproperties.h"
#include "core/pipeline/abstractworkflow.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/visualizationprocessor.h"
#include "modules/base/processors/lightsourceprovider.h"
......
%module devil
%include std_string.i
%include "core/bindings/campvis.i"
%import "core/bindings/campvis.i"
%{
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/allproperties.h"
#include "core/pipeline/abstractworkflow.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/visualizationprocessor.h"
#include "modules/devil/processors/devilimagereader.h"
#include "modules/devil/processors/devilimagewriter.h"
%}
......
%module cvio
%include std_string.i
%include "core/bindings/campvis.i"
%import "core/bindings/campvis.i"
%{
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/allproperties.h"
#include "core/pipeline/abstractworkflow.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/visualizationprocessor.h"
#include "modules/io/processors/mhdimagereader.h"
#include "modules/io/processors/mhdimagewriter.h"
%}
......
%module preprocessing
%include std_string.i
%include "core/bindings/campvis.i"
%import "core/bindings/campvis.i"
%{
#include "core/properties/allproperties.h"
#include "core/pipeline/abstractworkflow.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/visualizationprocessor.h"
#include "modules/preprocessing/processors/glimageresampler.h"
%}
......
%module vis
%include std_string.i
%include "core/bindings/campvis.i"
%import "core/bindings/campvis.i"
%{
#include "core/properties/allproperties.h"
#include "core/pipeline/abstractworkflow.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/pipeline/visualizationprocessor.h"
#include "modules/vis/processors/volumeexplorer.h"
#include "modules/vis/processors/volumerenderer.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment