[HDK] - How to get the creation time of nodes

   5109   11   0
User Avatar
Member
678 posts
Joined: July 2005
Offline
I decided to steal topic from Magneto .

I would like to extend HOM with HDK. I need to get those dates


What part of the HDK gives me access to them?
User Avatar
Staff
2590 posts
Joined: July 2005
Offline
mantragora
I decided to steal topic from Magneto .

I would like to extend HOM with HDK. I need to get those dates


What part of the HDK gives me access to them?


const OP_Stat &stat = node->getStat();
time_t st_create = stat.getCreateTime();
User Avatar
Member
678 posts
Joined: July 2005
Offline
Thank you!
User Avatar
Member
678 posts
Joined: July 2005
Offline
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?
User Avatar
Member
1904 posts
Joined: Nov. 2006
Online
I have a very limited knowledge of using the Python C API, but after getting your code to compile, the problem comes from this line:
PY_PyArg_ParseTuple(args, “si”, &nodePath)

You need to remove the ‘i’ entry so that Python only looks for a string argument and not a string + int (like in the HDK example). Removing that resulted in the function call working.

We've used this method to do some custom HOM extensions but now we just use inlinecpp since it is more flexible and way quicker to use. To me, the primary downfall of the HOMextendLibrary() method is that there is basically no support for geometry. Other than suggesting inlinecpp I'm afraid I can't offer much else of use in this case.

You might be best contacting support, though they may just tell you to use inlinecpp since the HOMextendLibrary method is basically deprecated.
Graham Thompson, Technical Artist @ Rockstar Games
User Avatar
Member
678 posts
Joined: July 2005
Offline
Thanks.

Once you got the workflow in place It is very fast to scratch working extensions. It just that there is not much info about conversion to Python object.
User Avatar
Member
678 posts
Joined: July 2005
Offline
cout'ing back the value I get from stats() gives me date in this format:

1398367851


How should I format/convert it to make it more readable?
User Avatar
Member
606 posts
Joined: May 2007
Offline
One answer is in your other thread [sidefx.com]:

>>> time.ctime(1398367851)
'Thu Apr 24 22:30:51 2014'

I don't know the C equivalent, though.
User Avatar
Member
678 posts
Joined: July 2005
Offline
I think I need to #include <ctime>

http://www.cplusplus.com/reference/ctime/ [cplusplus.com]
User Avatar
Member
678 posts
Joined: July 2005
Offline
I see that there is PY_FUNC_SEQ_PyString_FromString macro in PY_CPythonAPI.h that wraps PyString_FromString(), but if I try to call it I get error that PyString_FromString is undefined. nd yes, PY_CPythonAPI.h is the first file I include.

Should I include something more beside PY_CPythonAPI.h to make it work?
User Avatar
Staff
270 posts
Joined: July 2005
Offline
Are you calling PY_PyString_FromString?
User Avatar
Member
678 posts
Joined: July 2005
Offline
Sure I'm.

Now.

Thanks!
  • Quick Links