Skip to content

Instantly share code, notes, and snippets.

@yusukei
Last active January 29, 2021 15:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yusukei/4593097 to your computer and use it in GitHub Desktop.
Save yusukei/4593097 to your computer and use it in GitHub Desktop.
Python embedded for AfterEffects.
#include "SoSharedLibDefs.h"
#include "SoCClient.h"
#define EXPORT extern "C" __declspec(dllexport)
#define strdup _strdup
// ------------------------------------------------------------------
// 宣言
// ------------------------------------------------------------------
ESerror_t objectInitialize(SoHObject hObject,int argc, TaggedData* argv);
ESerror_t objectFinalize(SoHObject hObject);
ESerror_t objectGet(SoHObject hObject,SoCClientName* name,TaggedData* pResult);
ESerror_t objectPut(SoHObject hObject,SoCClientName* name,TaggedData* pValue);
ESerror_t objectCall(SoHObject hObject,SoCClientName* name,int argc,TaggedData* argv,TaggedData* pResult);
class PyAE
{
public:
static ESerror_t constructor(SoHObject hObject,int argc, TaggedData* argv);
static ESerror_t call(SoHObject hObject, SoCClientName* name,
int argc, TaggedData* argv, TaggedData* pResult);
static ESerror_t destructor(SoHObject hObject);
};
// ------------------------------------------------------------------
// グローバル変数
// ------------------------------------------------------------------
// ExtendScriptとやり取りするためのインターフェイス
SoServerInterface* gpServer = NULL;
SoHServer ghServer = NULL;
// Pythonをevalする際のオブジェクト空間
PyObject* gGlobals = NULL;
// ExtendScript側のPyクラス
SoObjectInterface objectInterface =
{
PyAE::constructor, // initialize
NULL, // put
NULL, // get
PyAE::call, // call
NULL, // valueOf
NULL, // toString
PyAE::destructor // finalize
};
// ------------------------------------------------------------------
// Export 関数
// ------------------------------------------------------------------
EXPORT void* ESMallocMem(size_t nBytes)
{
void* p = malloc(nBytes);
return p ;
}
EXPORT void ESFreeMem(void* p)
{
if (p)
free(p);
}
EXPORT char* ESInitialize(TaggedData* argv, long argc)
{
return "";
}
EXPORT long ESGetVersion(void)
{
return 1;
}
EXPORT void ESTerminate (void)
{
}
// ------------------------------------------------------------------
// 関数定義
// ------------------------------------------------------------------
// PyObject -> TaggedDataへ変換する
void py2as(PyObject* pyObj, TaggedData* aeObj)
{
if (PyInt_Check(pyObj)||PyLong_Check(pyObj))
{
aeObj->data.intval = PyInt_AsLong(pyObj);
aeObj->type = kTypeInteger;
}
else if (PyFloat_Check(pyObj))
{
aeObj->data.fltval = PyFloat_AsDouble(pyObj);
aeObj->type = kTypeDouble;
}
else if (PyString_Check(pyObj))
{
aeObj->data.string = strdup(PyString_AsString(pyObj));
aeObj->type = kTypeString;
}
}
// PyAEクラスのコンストラクタ
ESerror_t PyAE::constructor(SoHObject hObject,int argc, TaggedData* argv)
{
gpServer->addMethod(hObject, "eval", 0, NULL);
return kESErrOK;
}
// PyAEクラスのメソッドをcallすると呼ばれる
ESerror_t PyAE::call(SoHObject hObject, SoCClientName* name,
int argc, TaggedData* argv, TaggedData* pResult)
{
// name->name_sigにcallされたメソッド名が入っている
if (strcmp(name->name_sig, "eval")==0)
return PyAE::pyEval(hObject, name, argc, argv, pResult);
return kESErrNotImplemented;
}
// PyAEクラスのデストラクタ
ESerror_t PyAE::destructor(SoHObject hObject)
{
return kESErrOK;
}
// Pythonのevalを行う
ESerror_t PyAE::pyEval(SoHObject hObject, SoCClientName* name,
int argc, TaggedData* argv, TaggedData* pResult)
{
if (argc!=1)
return kESErrBadArgumentList;
int start_symbol = Py_eval_input;
// 引数に渡された文字列をPythonでevalする
PyObject* ret = PyRun_String(argv[0].data.string, start_symbol, gGlobals, gGlobals);
if (ret==NULL) {
PyErr_Print();
PyErr_Clear();
return kESErrException;
}
py2as(ret, pResult);
Py_DECREF(ret);
return kESErrOK;
}
// 初期化・終了初期化関数
EXPORT int ESClientInterface(SoCClient_e kReason,
SoServerInterface* pServer,
SoHServer hServer)
{
ESerror_t ret = kESErrOK;
// AfterEffectsのインスタンス
gpServer = pServer;
ghServer = hServer;
switch ( kReason )
{
case kSoCClient_init : {
// Pythonの初期化
Py_SetPythonHome("C:/Python26");
Py_Initialize();
printf("Py_Initialize\n");
// globals空間の生成
PyObject* main = PyImport_AddModule("__main__");
gGlobals = PyModule_GetDict(main);
// ExtendScriptにPyAEクラスを登録する
ret = gpServer->addClass(hServer, "PyAE", &objectInterface) ;
if (ret!=kESErrOK)
printf("Failed register pyAE Class.\n");
return 0;
} break ;
case kSoCClient_term : {
// Pythonの終了
Py_Finalize();
return 0 ;
} break ;
}
return 0 ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment