Last active
January 29, 2021 15:11
-
-
Save yusukei/4593097 to your computer and use it in GitHub Desktop.
Python embedded for AfterEffects.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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