This is my code:
HOM_Common.h
#pragma once
/* ———————————————————————
INCLUDES
——————————————————————— */
#include <PY/PY_CPythonAPI.h>
#include <HOM/HOM_Module.h>
#include <PY/PY_Python.h>
#include <PY/PY_InterpreterAutoLock.h>
#include <PY/PY_AutoObject.h>
#include <OBJ/OBJ_Node.h>
#include <OP/OP_Director.h>
#include <UT/UT_SysSpecific.h>
#include <UT/UT_UndoManager.h>
#include <ostream>
using std::cout;
using std::endl;
/* ———————————————————————
HOM_NodeInfo
——————————————————————— */
//#define GET_CREATIONTIME_DOC
HOM_NodeInfo.h
#pragma once
#include “HOM_Common.h”
namespace Mantragora
{
namespace HOM
{
class HOM_NodeInfo
{
public:
static PY_PyMethodDef
GetCreationTime;
static PY_PyMethodDef
GetModifyTime;
static PY_PyMethodDef
GetMemoryUsage;
static auto
GetCreationTime_Wrapper (PY_PyObject* self, PY_PyObject* args)
-> PY_PyObject*;
private:
static auto
_createHouException (const char* exceptionclassname, const char* instancemessage, PY_PyObject*& exceptionclass)
-> PY_PyObject*;
static auto
_getCreationTime (const char* nodepath) throw(HOM_OperationFailed)
-> time_t;
};
}
}
HOM_NodeInfo.cpp
#include “HOM_NodeInfo.h”
using namespace Mantragora::HOM;
/* ———————————————————————
PARAMETERS
——————————————————————— */
PY_PyMethodDef
HOM_NodeInfo::GetCreationTime =
{
“_getCreationTime”, // name of method that executes task
HOM_NodeInfo::GetCreationTime_Wrapper, // wrapper for the method
PY_METH_VARARGS(), // wtf is this?
NULL // documentation
};
/* ———————————————————————
EXCEPTIONS
——————————————————————— */
auto
HOM_NodeInfo::_createHouException(const char* exceptionclassname, const char* instancemessage, PY_PyObject*& exceptionclass)
-> PY_PyObject*
{
exceptionclass = NULL;
// import hou
auto houModule = PY_AutoObject(PY_PyImport_ImportModule(“hou”));
// look up the exception by name in the module's dictionary
auto houModuleDict = PY_PyModule_GetDict(houModule);
exceptionclass = PY_PyDict_GetItemString(houModuleDict, exceptionclassname);
// PY_PyDict_GetItemString doesn't set a Python exception, so we are careful
// to set it ourselves if the class name isn't valid.
if (!exceptionclass)
{
PY_PyErr_SetString(PY_PyExc_RuntimeError(), “Could not find exception class in hou module”);
return NULL;
}
// create an instance of the exception
// first create a tuple containing the arguments to __init__
PY_AutoObject args(PY_Py_BuildValue(“(s)”, instancemessage));
if (!args) return NULL;
return PY_PyObject_Call(exceptionclass, args, /*kwargs=*/NULL);
}
/* ———————————————————————
WRAPPERS
——————————————————————— */
auto
HOM_NodeInfo::GetCreationTime_Wrapper(PY_PyObject* self, PY_PyObject* args)
-> PY_PyObject*
{
// first extract the arguments
const char* nodePath;
if (!PY_PyArg_ParseTuple(args, “si”, &nodePath)) return NULL;
// now do actual work
try
{
// this will make sure that any code that accesses Houdini's internal state is threadsafe
HOM_AutoLock hom_lock;
// call the wrapped function to do the actual work
auto creationTime = HOM_NodeInfo::_getCreationTime(nodePath);
// convert creationTime to python object and return
// return PY_Py_None to indicate that no error occurred
return PY_Py_None();
}
catch (HOM_Error& error)
{
// get exception class name
auto exceptionClassName = UTunmangleClassNameFromTypeIdName(typeid(error).name());
if (exceptionClassName.find(“HOM_”) == 0) exceptionClassName = exceptionClassName.substr(4);
// create exception
PY_PyObject* exceptionClass;
auto exceptionInstance = PY_AutoObject(HOM_NodeInfo::_createHouException(exceptionClassName.c_str(), error.instanceMessage().c_str(), exceptionClass));
if (!exceptionInstance) return NULL;
PY_PyErr_SetObject(exceptionClass, exceptionInstance);
return NULL;
}
};
/* ———————————————————————
MAIN
——————————————————————— */
auto
HOM_NodeInfo::_getCreationTime(const char* nodepath) throw(HOM_OperationFailed) //, HOM_PermissionError)
-> time_t
{
// find the operator
auto op = OPgetDirector()->findNode(nodepath);
if (!op) throw HOM_OperationFailed(“Internal error (could not find node)”);
// Ready?! Steady?! GO!!!
auto stat = op->getStat();
auto creation = stat.getCreateTime();
// … aaaand FINISH!
return creation;
}
HOM_Registration.cpp
#define FINAL
#include <UT/UT_DSOVersion.h>
#include “HOM_NodeInfo.h”
#ifdef FINAL
#include “HOM_NodeInfo.cpp”
#endif
using namespace Mantragora::HOM;
/* ———————————————————————
REGISTRATION
——————————————————————— */
static PY_PyMethodDef
Methods =
{
HOM_NodeInfo::GetCreationTime,
{ NULL, NULL, 0, NULL }
};
auto
HOMextendLibrary()
-> void
{
PY_InterpreterAutoLock interpreter_auto_lock;
// create module and add methods
auto module = PY_Py_InitModule(“mantragora”, Methods);
// be careful to maintain whitespace
auto success = PYrunPythonStatementsAndExpectNoErrors(
“def _getCreationTime(self):\n”
“ ‘'’Get creation time of the node.'''\n”
“ import mantragora\n”
“ mantragora._getCreationTime(self.path())\n”
“__import__('hou').Node.getCreationTime = _getCreationTime\n”
“del _getCreationTime\n”);
}
Why I'm getting:
Traceback (most recent call last):
File “<console>”, line 1, in <module>
TypeError: _getCreationTime() takes exactly 1 argument (2 given)
while my function doesn't expect any arguments?
Is it because of two argumensts that are passed to Wrapper function?
If yes, how I should rewrite it?
If I remove this second argument from my wrapper I can't extract “nodepath” that is needed to extract creation time, so how to solve this?
Is there any more info about expanding HOM with HDK than just one example in HDK Documentation?
And how to convert from C++ to Python object my return value? ARe there any examples somewhere of possibe convertions? (I mean HDK examples, not info from inlineCpp)
Oh, and what PY_METH_VARARGS() flag means?