Smooth Cpp Shared
openforecast-org/smooth
Work on the C++ layer that the R package and the Python port share — the headers under src/headers/, the Rcpp bindings in src/, the pybind11 bindings in src/python/, and the two build systems that…
A skill your agent uses when adding new Python bindings (exposing C++ classes/functions to Python) in the DAWorkBench project, or modifying existing bindings.
$ npx skills add czyt1988/data-workbench --skill add-python-binding -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install czyt1988/data-workbench add-python-binding --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/czyt1988/data-workbench.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/add-python-binding .claude/skills/add-python-binding && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "add-python-binding" agent skill from https://github.com/czyt1988/data-workbench/tree/master/skills/add-python-binding into .claude/skills/add-python-binding/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "add-python-binding", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/czyt1988/data-workbench/tree/master/skills/add-python-bindingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add czyt1988/data-workbench --skill add-python-binding -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install czyt1988/data-workbench add-python-binding --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/czyt1988/data-workbench.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/add-python-binding .agents/skills/add-python-binding && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "add-python-binding" agent skill from https://github.com/czyt1988/data-workbench/tree/master/skills/add-python-binding into .agents/skills/add-python-binding/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "add-python-binding", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add czyt1988/data-workbench --skill add-python-binding -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install czyt1988/data-workbench add-python-binding --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/czyt1988/data-workbench.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/add-python-binding .cursor/skills/add-python-binding && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "add-python-binding" agent skill from https://github.com/czyt1988/data-workbench/tree/master/skills/add-python-binding into .cursor/skills/add-python-binding/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "add-python-binding", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/czyt1988/data-workbench.git --path skills/add-python-binding--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add czyt1988/data-workbench --skill add-python-binding -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install czyt1988/data-workbench add-python-binding --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/czyt1988/data-workbench.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/add-python-binding .gemini/skills/add-python-binding && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "add-python-binding" agent skill from https://github.com/czyt1988/data-workbench/tree/master/skills/add-python-binding into .gemini/skills/add-python-binding/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "add-python-binding", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install czyt1988/data-workbench add-python-bindingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add czyt1988/data-workbench --skill add-python-binding -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/czyt1988/data-workbench.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/add-python-binding .github/skills/add-python-binding && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "add-python-binding" agent skill from https://github.com/czyt1988/data-workbench/tree/master/skills/add-python-binding into .github/skills/add-python-binding/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "add-python-binding", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add czyt1988/data-workbench --skill add-python-binding -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install czyt1988/data-workbench add-python-binding --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/czyt1988/data-workbench.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/add-python-binding .opencode/skills/add-python-binding && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "add-python-binding" agent skill from https://github.com/czyt1988/data-workbench/tree/master/skills/add-python-binding into .opencode/skills/add-python-binding/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "add-python-binding", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
add-python-bindingA skill your agent uses when adding new Python bindings (exposing C++ classes/functions to Python) in the DAWorkBench project, or modifying existing bindings.
Add Python Binding is an agent skill from czyt1988/data-workbench. Use when adding new Python bindings (exposing C++ classes/functions to Python) in the DAWorkBench project, or modifying existing bindings. Trigger words: python binding, pybind11 binding, expose to python, add binding, export python module, bind C++ to Python.
Its SKILL.md is about 4.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `SKILL_cn.md`).
It sits in Data & Analytics. It works with Python and C++. The repository describes itself as: AI Agent-driven data analysis workbench built on C++17/Qt: directed-graph workflow engine, embedded Python (pandas/numpy), interactive publication-quality charts, C++ & Python… The licence is LGPL-3.0.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit cf3bbda. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are cpp).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Add Python Binding loads about 4.6k tokens when it runs. Until then it costs about 70 tokens; SKILL.md has 1,008 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from czyt1988/data-workbench at commit cf3bbda, republished under its LGPL-3.0 licence (© czyt1988). 1,008 words, ~4,639 tokens.
.claude/skills/add-python-binding/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.This skill guides adding Python bindings for C++ code in the DAWorkBench project. The project uses pybind11 embedded mode (PYBIND11_EMBEDDED_MODULE) to expose C++ classes and functions to the Python scripting environment. Bindings fall into four scenarios, each with distinct patterns and key points.
What are you binding?
├── A standalone free function or singleton accessor → Scenario A: Simple Function Binding
├── A Qt-interfacing class (with QString/QList etc. parameters) → Scenario B: Qt-Interfacing Class Binding
├── A data wrapper class (pandas/numpy object wrapper) → Scenario C: Data Wrapper Binding
└── C++ needs to call Python functions → Scenario D: Python Module ImportBefore including any pybind11 header, you must first include DAPybind11InQt.h. Qt's slots macro conflicts with pybind11. This header handles the #undef slots → include pybind11 → #define slots Q_SLOTS toggle.
#include "DAPybind11InQt.h" // 必须是第一个pybind11相关头文件Use for: Standalone free functions, singleton accessors (no Qt type parameters).
// MyPythonBinding.h
#ifndef MYPYTHONBINDING_H
#define MYPYTHONBINDING_H
#include <string>
namespace DA {
void myHelperFunction(const std::string& msg);
DA::DACoreInterface* getMyCorePtr();
}
#endif
// MyPythonBinding.cpp
#include "MyPythonBinding.h"
#include "DAPybind11InQt.h" // slots workaround,必须第一个
#include "DACoreInterface.h"
namespace DA {
void myHelperFunction(const std::string& msg) {
qInfo() << QString::fromStdString(msg);
}
}
PYBIND11_EMBEDDED_MODULE(da_my_module, m)
{
// 单例访问器:必须使用 return_value_policy::reference
m.def("getCore",
&DA::getMyCorePtr,
"Return the core interface (singleton)",
pybind11::return_value_policy::reference);
// 自由函数:默认策略即可
m.def("myHelper", &DA::myHelperFunction, "A helper function");
}#include "DAPybind11InQt.h" as the first pybind11-related headerPYBIND11_EMBEDDED_MODULE(module_name, m).def() for free functionspybind11::return_value_policy::reference, otherwise pybind11 will try to destruct itda_xxx prefix convention重要:所有返回裸指针
T*的工厂方法(如addHistogram、addCurve等)也必须指定return_value_policy::reference,否则 Python GC 会 delete 底层 C++ 对象。详见项目技能pybind11-return-value-policy。
| File | Purpose |
|---|---|
src/APP/PythonBinding/DAAppPythonBinding.cpp | Full Scenario A example |
src/APP/PythonBinding/DAAppPythonBinding.h | Function declaration template |
src/DAPyBindQt/DAPybind11InQt.h | slots workaround |
Use for: Interface classes with QString, QList, QJsonObject and other Qt type parameters.
#include "DAPybind11InQt.h" // slots workaround,必须第一个
#include "DAPybind11QtCaster.hpp" // Qt类型转换器
#include "DAPythonSignalHandler.h"
#include "MyQtInterface.h"
PYBIND11_EMBEDDED_MODULE(da_my_interface, m)
{
// 1. 绑定类
pybind11::class_<DA::MyQtInterface>(m, "MyQtInterface")
// 2. QString参数 → lambda包装,用 std::string 接收再转换
.def("showMessage",
[](DA::MyQtInterface& self, const std::string& message, int timeout) {
self.showMessage(QString::fromStdString(message), timeout);
},
pybind11::arg("message"),
pybind11::arg("timeout") = 15000)
// 3. 返回内部对象 → reference_internal
.def("getSubInterface",
&DA::MyQtInterface::getSubInterface,
pybind11::return_value_policy::reference_internal)
// 4. QList<T>返回值 → lambda手动转为 pybind11::list
.def("getAllItems",
[](DA::MyQtInterface& self) {
QList<DA::MyItem> items = self.getAllItems();
pybind11::list pyList;
for (const DA::MyItem& item : items) {
pyList.append(item);
}
return pyList;
},
"Get all items as a Python list")
// 5. JSON配置对话框(getConfigValues模式)
.def("getConfigValues",
[](DA::MyQtInterface& self, const std::string& jsonConfig, const std::string& cacheKey) {
QJsonObject jsonObj = self.getConfigValues(
QString::fromStdString(jsonConfig),
self.getMainWindow(),
QString::fromStdString(cacheKey));
return DA::PY::qjsonObjectToPyDict(jsonObj);
},
pybind11::arg("jsonConfig"),
pybind11::arg("cacheKey") = "")
;
// 6. 跨线程通信(如需从Python回调到Qt主线程)
pybind11::class_<DA::DAPythonSignalHandler>(m, "DAPythonSignalHandler")
.def(pybind11::init<>())
.def("callInMainThread",
[](DA::DAPythonSignalHandler& self, pybind11::function pyFunc) {
self.callInMainThread([pyFunc]() {
try {
pybind11::gil_scoped_acquire acquire;
pyFunc();
} catch (const pybind11::error_already_set& e) {
qCritical() << "Python error in main thread callback:" << e.what();
}
});
},
pybind11::arg("func"));
}#include "DAPybind11InQt.h" as the first pybind11-related header (!!!danger mandatory)#include "DAPybind11QtCaster.hpp" to bring in Qt type casterspybind11::class_<>() to bind the interface classQString parameters: lambda wrapper, receive std::string then convert with QString::fromStdString()pybind11::return_value_policy::reference_internal (lifetime bound to parent object)QList<T> returns: lambda manually iterates and converts to pybind11::list (cannot rely on automatic QList caster)getConfigValues: std::string JSON → QString → dialog → QJsonObject → DA::PY::qjsonObjectToPyDict() to pybind11::dictDAPythonSignalHandler::callInMainThread + pybind11::gil_scoped_acquire| File | Purpose |
|---|---|
src/DAInterface/DAInterfacePythonBinding.cpp | Full Scenario B example |
src/DAPyBindQt/DAPybind11QtCaster.hpp | Qt type casters |
src/DAPyBindQt/DAPythonSignalHandler.h | Cross-thread communication |
src/DAPyBindQt/DAPyJsonCast.h | QJsonObject ↔ pybind11::dict |
Use for: C++ classes that wrap pandas/numpy Python objects (e.g. DAData, DAPyDataFrame).
// MyDataPythonBinding.h — 推荐:写doxygen API参考
#ifndef MYDATAPYTHONBINDING_H
#define MYDATAPYTHONBINDING_H
/**
* @file MyDataPythonBinding
* @brief Python 绑定模块 da_my_data 的完整 API 清单与调用示例
*
* @section py_overview 一、模块功能
* da_my_data 模块把 C++ 的数据包装类暴露给 Python,使脚本能够:
* - 直接读取/构造 pandas 对象并封装为 MyData;
* - 将 MyData 加入管理器;
* - 查询、删除等常规管理操作。
*
* @section py_class_list 二、导出类型一览
* | Python 类/枚举 | 对应 C++ 类型 | 说明 |
* |----------------|---------------|------|
* | MyData | DA::MyData | 轻量包装 |
* | MyEnum | DA::MyEnum | 状态枚举 |
*
* @section py_example 三、完整示例
* @code{.py}
* import pandas as pd
* import da_my_data
* df = pd.read_csv("example.csv")
* data = da_my_data.MyData(df)
* data.setName("csv_example")
* @endcode
*/
#include "DAPybind11InQt.h"
#include "MyData.h"
DA::DAPyDataFrame pyDataFrameToDAPyDataFrame(pybind11::object df);
void addDataFrameFromPy(DA::MyDataManager& mgr, pybind11::object df, const std::string& name);
#endif
// MyDataPythonBinding.cpp
#include "MyDataPythonBinding.h"
#include "DAPybind11InQt.h" // slots workaround
#include "MyData.h"
DA::DAPyDataFrame pyDataFrameToDAPyDataFrame(pybind11::object df)
{
return DA::DAPyDataFrame(df);
}
void addDataFrameFromPy(DA::MyDataManager& mgr, pybind11::object df, const std::string& name)
{
DA::DAPyDataFrame daDf = pyDataFrameToDAPyDataFrame(df);
DA::MyData data(daDf);
data.setName(QString::fromStdString(name));
mgr.addData(data);
}
PYBIND11_EMBEDDED_MODULE(da_my_data, m)
{
// 1. 绑定数据包装类
pybind11::class_<DA::MyData>(m, "MyData")
.def(pybind11::init<>()) // 默认构造
.def(pybind11::init<pybind11::object>()) // 直接接受 pandas 对象
.def("toPyObject", &DA::MyData::toPyObject, "Return the underlying pandas object")
.def("getName", [](const DA::MyData& self) { return self.getName().toStdString(); })
.def("setName", [](DA::MyData& self, const std::string& n) { self.setName(QString::fromStdString(n)); })
.def("isNull", &DA::MyData::isNull, "Check if the data is null")
.def("id", &DA::MyData::id, "Return the data id");
// 2. 导出枚举
pybind11::enum_<DA::MyDataManager::ChangeType>(m, "DataChangeType")
.value("Name", DA::MyDataManager::ChangeName)
.value("Value", DA::MyDataManager::ChangeValue)
.export_values();
// 3. 绑定数据管理器
pybind11::class_<DA::MyDataManager>(m, "MyDataManager")
.def("addDataFrame", &addDataFrameFromPy, "Add a pandas DataFrame to manager")
.def("addData",
static_cast<void(DA::MyDataManager::*)(DA::MyData&)>(&DA::MyDataManager::addData),
"Add a MyData object to manager")
.def("getDataCount", &DA::MyDataManager::getDataCount)
// QList → pybind11::list 手动转换
.def("getAllDatas",
[](DA::MyDataManager& self) {
QList<DA::MyData> datas = self.getAllDatas();
pybind11::list pyList;
for (const DA::MyData& data : datas) { pyList.append(data); }
return pyList;
});
}#include "DAPybind11InQt.h" as the first pybind11-related headerpybind11::init<pybind11::object>() constructor accepts pandas objectsQString properties: lambda wrapper with std::string ↔ QString conversionpybind11::enum_<>() + .value() + .export_values() to export enumsQList<T> returns: lambda manually converts to pybind11::liststatic_cast<function_signature>(&Class::method) to select the correct overload.h file (type table + construction notes + member docs + examples + limitations)| File | Purpose |
|---|---|
src/DAData/DADataPythonBinding.cpp | Full Scenario C example |
src/DAData/DADataPythonBinding.h | .h doxygen API reference example (143 lines, best practice) |
Use for: C++ needs to call Python functions (e.g. numpy/pandas APIs), not exposing C++ to Python.
// DAPyModuleMyLib.h
#ifndef DAPYMODULEMYLIB_H
#define DAPYMODULEMYLIB_H
#include "DAPyBindQtGlobal.h"
#include "DAPyModule.h"
namespace DA {
class DAPYBINDQT_API DAPyModuleMyLib : public DAPyModule
{
DA_DECLARE_PRIVATE(DAPyModuleMyLib)
DAPyModuleMyLib();
public:
~DAPyModuleMyLib();
static DAPyModuleMyLib& getInstance();
void finalize();
bool import();
// 暴露缓存好的Python函数/类型
bool isInstanceMyType(const pybind11::object& obj) const;
private:
// PrivateData 中缓存 Python 对象引用
};
} // namespace DA
#endif
// DAPyModuleMyLib.cpp
#include "DAPyModuleMyLib.h"
#include "DAPybind11InQt.h" // slots workaround
#include <QDebug>
namespace DA {
class DAPyModuleMyLib::PrivateData
{
DA_DECLARE_PUBLIC(DAPyModuleMyLib)
public:
PrivateData(DAPyModuleMyLib* p);
QString mLastErrorString;
// 缓存 Python 函数/类型引用,避免每次 attr() 查找
pybind11::object mObjMyType;
pybind11::object mObjMyFunc;
};
DAPyModuleMyLib::PrivateData::PrivateData(DAPyModuleMyLib* p) : q_ptr(p) {}
DAPyModuleMyLib::DAPyModuleMyLib() : DAPyModule(), DA_PIMPL_CONSTRUCT
{
import(); // 1. 先导入模块
try {
// 2. 惰性缓存关键 Python 对象
d_ptr->mObjMyType = attr("MyType");
d_ptr->mObjMyFunc = attr("my_function");
} catch (const std::exception& e) {
d_ptr->mLastErrorString = e.what();
}
}
bool DAPyModuleMyLib::import()
{
return DAPyModule::import("my_lib"); // 3. 调用基类 importModule
}
bool DAPyModuleMyLib::isInstanceMyType(const pybind11::object& obj) const
{
return pybind11::isinstance(obj, d_ptr->mObjMyType);
}
DAPyModuleMyLib& DAPyModuleMyLib::getInstance()
{
static DAPyModuleMyLib s_instance;
return s_instance;
}
}DAPyModule (which inherits DAPyObjectWrapper, not QObject)DA_DECLARE_PRIVATE / DA_PIMPL_CONSTRUCT)import() in constructor → DAPyModule::import("module_name") to import the Python moduleattr("name") to get Python object references, cache them in PrivateData (avoids repeated lookup overhead)pybind11::isinstance(obj, cached_type) for type checkinggetInstance() returns a static instance| File | Purpose |
|---|---|
src/DAPyBindQt/numpy/DAPyModuleNumpy.h | Scenario D header template |
src/DAPyBindQt/numpy/DAPyModuleNumpy.cpp | Scenario D full implementation example |
src/DAPyBindQt/DAPyModule.h | DAPyModule base class API |
| Aspect | Scenario A | Scenario B | Scenario C | Scenario D |
|---|---|---|---|---|
| Base pattern | PYBIND11_EMBEDDED_MODULE + .def() | PYBIND11_EMBEDDED_MODULE + class_<>() | PYBIND11_EMBEDDED_MODULE + class_<>() + enum_<>() | Inherit DAPyModule, no PYBIND11_EMBEDDED_MODULE |
| Qt type handling | None (pure std::string) | Lambda wrapping QString / manual QList conversion | Lambda wrapping QString | None (C++ calls Python, no Qt types exposed) |
| Ownership policy | reference (singleton) | reference_internal (child bound to parent lifetime) | Default (wrapper manages itself) | N/A (C++ side holds pybind11::object) |
| Enum export | Not applicable | Not applicable | pybind11::enum_<>() + .export_values() | Not applicable |
| .h doxygen API reference | Concise function declarations | Can be omitted (see DAInterfacePythonBinding.h, only 4 lines) | Recommended (see DADataPythonBinding.h, 143 lines) | Not applicable (PIMPL class) |
| Stub update | Add da_my_module.pyi | Add da_my_interface.pyi | Add da_my_data.pyi | Not applicable |
After adding a new Python binding module, these files must be updated synchronously:
.pyi file following existing stub format (Chinese docstring + type annotations + cross-module imports). Watch for circular import edge cases: if the new module is referenced by da_interface, update da_interface/__init__.pyi imports too.py file following existing mock format. Note lazy-loading pattern: see stubs/mock/da_interface.py for avoiding circular dependenciesDAPybind11InQt.h handles #undef slots → include pybind11 → #define slots Q_SLOTS. All binding files must include this header firstQVector only exists in Qt5; in Qt6 QVector = QList. Use version-check macros if neededQButtonGroup::buttonClicked in Qt5 uses QOverload<int>::of(), Qt6 uses idClickedPython is a mandatory dependency and is always built. Binding code must not be wrapped in any conditional compilation guards or #ifdef macros. In CMakeLists.txt, add binding files unconditionally — there is no conditional CMake block that gates Python.
Only bind public methods. Never attempt to bind DA_D pointers or PrivateData members. PIMPL private data must not be exposed to Python.
QwtPlotItem-related classes do not inherit QObject, so Q_OBJECT macro is not allowed. Do not use dynamic properties when binding them.
<BoundType>Requires lambda manual conversion to pybind11::list (iterate and append each item). Cannot rely on automatic QList caster because bound types may not have registered one.
DAPybind11QtCaster.hpp provides a QVariant caster supporting numpy object conversion, but not all Qt type combinations can serve as QHash keys.
| File | Path | Purpose |
|---|---|---|
| DAAppPythonBinding.cpp | src/APP/PythonBinding/ | Scenario A reference |
| DAAppPythonBinding.h | src/APP/PythonBinding/ | Scenario A function declaration template |
| DAInterfacePythonBinding.cpp | src/DAInterface/ | Scenario B reference (Qt-interfacing class + lambda wrapping + QList conversion) |
| DADataPythonBinding.cpp | src/DAData/ | Scenario C reference (data wrapper class + enum export) |
| DADataPythonBinding.h | src/DAData/ | .h doxygen API reference example (143 lines) |
| DAPyModuleNumpy.h/.cpp | src/DAPyBindQt/numpy/ | Scenario D reference (module import + lazy caching) |
| DAPyModule.h | src/DAPyBindQt/ | DAPyModule base class API |
| DAPybind11InQt.h | src/DAPyBindQt/ | slots workaround (mandatory for all scenarios) |
| DAPybind11QtCaster.hpp | src/DAPyBindQt/ | Qt type casters |
| DAPyInterpreter.h | src/DAPyBindQt/ | Python interpreter management |
| DAPythonSignalHandler.h | src/DAPyBindQt/ | Cross-thread communication |
| stubs/da_interface/init.pyi | stubs/da_interface/ | Stub format reference |
| stubs/mock/da_interface.py | stubs/mock/ | Mock format reference (lazy-loading pattern) |
© czyt1988, LGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in skills/add-python-binding of czyt1988/data-workbench.
Open the folder on GitHubat commit cf3bbda
Add Python Binding next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Add Python Binding this skillczyt1988/data-workbench | 102 | — | ~4.6k | Automated safety check: Pass | LGPL-3.0 | |
| Smooth Cpp Sharedopenforecast-org/smooth | 107 | — | ~1.1k | Automated safety check: Pass | LGPL-2.1 | |
| Elodin DBelodin-sys/elodin | 547 | — | ~2.8k | Automated safety check: Pass | Apache-2.0 | |
| GeomasterLeonChaoX/qinyan-academic-skills | 938 | 1 repos | ~2.9k | Automated safety check: Pass | MIT | |
| Geomasteragent-skills-hub/agent-skills-hub | 111 | 1 repos | ~5.2k | Automated safety check: Pass | MIT | |
| GeomasterK-Dense-AI/scientific-agent-skills | 48k | 1 repos | ~2.8k | Automated safety check: Pass | MIT |
openforecast-org/smooth
Work on the C++ layer that the R package and the Python port share — the headers under src/headers/, the Rcpp bindings in src/, the pybind11 bindings in src/python/, and the two build systems that…
elodin-sys/elodin
Work with Elodin-DB, the time-series telemetry database. An agent skill from elodin-sys/elodin.
LeonChaoX/qinyan-academic-skills
Comprehensive geospatial science skill covering remote sensing, GIS, spatial analysis, machine learning for earth observation, and 30+ scientific domains.
agent-skills-hub/agent-skills-hub
Comprehensive geospatial science skill covering remote sensing, GIS, spatial analysis, machine learning for earth observation, and 30+ scientific domains.
K-Dense-AI/scientific-agent-skills
Supports geospatial research workflows for remote sensing, vector and raster GIS, spatial statistics, terrain and network analysis, and machine learning for Earth observation.
secondsky/sap-skills
Develops data processing pipelines, integrations, and machine learning scenarios in SAP Data Intelligence Cloud.
czyt1988/data-workbench
A skill your agent uses when creating property panels or configuration UI in the data-workbench Qt/C++ project.
czyt1988/data-workbench
A skill your agent uses when creating a new C++ plugin DLL for the data-workbench platform, or modifying an existing plugin's structure, CMake, UI integration, or data access.
czyt1988/data-workbench
A skill your agent uses when integrating Python scripts with C++ in a DAWorkbench plugin — calling Python from C++, Python multithreading without UI conflicts, Python-to-C++ data exchange, Python UI…
Categories
A skill your agent uses when adding new Python bindings (exposing C++ classes/functions to Python) in the DAWorkBench project, or modifying existing bindings. Add Python Binding is an agent skill from czyt1988/data-workbench. Use when adding new Python bindings (exposing C++ classes/functions to Python) in the DAWorkBench project, or modifying existing bindings.
Add Python Binding fits situations like: adding new Python bindings (exposing C++ classes/functions to Python) in the DAWorkBench project; modifying existing bindings; words: python binding; pybind11 binding.
Run `npx skills add czyt1988/data-workbench --skill add-python-binding -a claude-code`. Or copy the skill folder (skills/add-python-binding in czyt1988/data-workbench) into .claude/skills/add-python-binding in your project. Claude Code loads it when a task matches its description.
Run `npx skills add czyt1988/data-workbench --skill add-python-binding -a codex`. Or copy the skill folder (skills/add-python-binding in czyt1988/data-workbench) into .agents/skills/add-python-binding in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add czyt1988/data-workbench --skill add-python-binding -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/add-python-binding, .gemini/skills/add-python-binding, .github/skills/add-python-binding and .opencode/skills/add-python-binding in your project.
SKILL.md names no scripts, command-line tools or credentials: Add Python Binding is instructions for the agent only. Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Add Python Binding is published under the LGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.6k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Add Python Binding: Smooth Cpp Shared (openforecast-org/smooth, 107 stars), Elodin DB (elodin-sys/elodin, 547 stars), Geomaster (LeonChaoX/qinyan-academic-skills, 938 stars) and Geomaster (agent-skills-hub/agent-skills-hub, 111 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
czyt1988 (a GitHub user) maintains it in czyt1988/data-workbench, which has 102 GitHub stars. The repository holds 4 skills in this directory. The repository was last updated on September 12, 2026.
Source: czyt1988/data-workbench on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.