Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 042cafbc authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

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