Touch Designer의 C++ 조작자와 Python의 합작

24010 단어 touchdesignertech

TouchDesigner의 C++ 운영자


터치 디자이너에서는 C++로 사용자 정의 프로그램 라이브러리를 제작해 독특한 기능을 가진 조작자를 만들 수 있다.이번 기사에서는 C++의 운영자 기초 부분에 대한 해설이 아직 완전히 설명되지 않았으니 ↓의 글 등을 참고하시기 바랍니다.
https://docs.derivative.ca/Custom_Operators
https://note.com/toyoshimorioka/n/nce76daf98907
http://satoruhiga.com/post/extending-touchdesigner/
이 보도에서 소개한 코드 샘플 항목은 여기에 있다
https://drive.google.com/file/d/1x4garLy7CiFHvM8AckT0KYAmmjxmUmAE/view?usp=sharing

C++ 운영자의 문제점


C++로 작업자를 만들면 터치 디자이너의 매개 변수 인터페이스와 노드의 입력, 출력을 사용하여 입력과 출력을 할 수 있다.
대부분의 경우 매개 변수와 노드를 연결할 수만 있다면 문제없다
  • C++ 작업자에서 이벤트를 호출할 때
  • 터치 디자인 측의 파이톤에서 조작자의 기능을 호출하고자 할 때
  • 하나의 처리를 통해 조작원 유형을 뛰어넘는 CHOP 데이터,DAT 데이터 등을 처리하고 싶을 때
  • 등 매개 변수와 입력 연결만 있으면 융통성 있게 처리하기 어려울 때도 있다.
    이 글에서, 나는 C++ 작업자가 파이톤에서 처리할 수 있는 기능을 추가하는 방법을 소개하고 싶다.

    키 포인트

    CPlusPlus_Common.h에서 정의한 OP_ParameterManager::appendPython()OP_Inputs::getParPython()에서 작업자는 파이톤으로 확장됩니다.


    이것은 Python 대상을 C++ 작업자의 매개 변수로 얻기 위해서, 이것을 사용하여 C++ 작업자와 터치 디자이너의 Python을 연결합니다.
    예를 들어, 다시 쓰기 함수 setupParameters 에서 실행 appendPython 할 때
    void setupParameters(OP_ParameterManager* manager, void* reserved1) override
    {
    	{
    		OP_StringParameter sp;
    		sp.label = "Python Parameter";
    		sp.name = "Pythonparam";
    		sp.page = "Test PyObject";
    		manager->appendPython(sp);
    	}
    }
    
    TouchDesigner의 매개변수 창에 매개변수를 추가합니다.

    C++ 운영자 측에서는 getOutputInfo 또는 executeOP_Inputs형 매개 변수를 사용하여 전달하는 방법inputs->getParPython()을 사용하여 추가 매개 변수에 접근할 수 있다.
    bool getOutputInfo(CHOP_OutputInfo* info, const OP_Inputs *inputs, void *reserved1) override
    {
    	info->numSamples = 600;
    	info->numChannels = 1;
    
    	PyObject* pyobj = inputs->getParPython("Pythonparam");
    	if (pyobj)
    	{
    		// PyObjectを使ったコードをここに記述
    		// ...
    	}
    
    	return true;
    }
    
    단, PyObject를 하려면 C++ 컴파일러에게 PyObject가 어떤 물건인지 전달해야 하기 때문에 PyObject의 SDK를 통과해야 합니다.이번 샘플 프로젝트는 cmake를 사용했기 때문에 include_directorieslink_directories에 각각 윈도에 설치된 파이톤3을 사용했다.보충 7의 경로.
    include_directories(
        "src"
        "derivative"
        "derivative/GL"
        ${CMAKE_CURRENT_SOURCE_DIR}/libs/include
        "C:/Python37/include"
    )
    
    link_directories(
        ${CMAKE_CURRENT_SOURCE_DIR}/libs/lib
        "C:/Python37/libs"
    )
    
    구축 시 LNK1104 cannot open file 'python37_d.lib' 등의 오류가 표시되면 구축 설정이 Debug이므로 Release로 변경됩니다.
    디버그 버전의 Pytohon 프로그램 라이브러리를 설치하면 디버그 설정도 구축할 수 있지만 실행할 때 예외가 생겨서 전진할 수 없는 경우가 많습니다.(TouchDesigner의 Python과 호환...?)

    시간을 지정하다


    조작자의 구축이 완료된 후에 TouchDesigner에 읽어서 실행하면 다음과 같은 오류가 발생할 수 있습니다.

    지정되지 않은 경우pythonVersion 오류, FillCHOPPluginInfo 등으로, 플러그인을 초기화할 때 사용하는 파이썬의 버전을 지정하면 오류가 발생하지 않습니다(터치 디자이너의 파이썬 버전 이외의 파이썬을 사용할 수 있는지 모르겠습니다...)
    DLLEXPORT void FillCHOPPluginInfo(CHOP_PluginInfo *info)
    {
    	// ...
    	
    	info->customOPInfo.pythonVersion->setString("3.7");
    }
    

    pybind11


    파이썬의 헤드와 라이브러리를 가져오면 파이썬 모듈의 개발처럼 구축할 수 있습니다. 파이썬 API는 C 언어로 작성되어 많은 코드가 한눈에 무엇을 하는지 알 수 없습니다.이런 일을 할 때 파이톤과 C++가 잘 연결된 pybind 11이라는 프로그램 라이브러리를 자주 사용합니다.
    https://github.com/pybind/pybind11
    pybind11은 머리만 있는 라이브러리이기 때문에 적당한 곳에 놓고 내부 통로를 통과하면 됩니다.이번 설정은 다음과 같다.
    include_directories(
        "src"
        "derivative"
        "derivative/GL"
        ${CMAKE_CURRENT_SOURCE_DIR}/libs/include
        "C:/Python37/include"
        "libs/pybind11/include" # pybind11
    )
    
    소스 코드 위
    #include <pybind11/pybind11.h>
    
    namespace py = pybind11;
    
    이렇게 하면 사용할 수 있습니다.간단하다getParPython()에서 얻은 PyObject*를pybind11 관리할 때↓와 같다.pybind 11의 대상 유형은 pybind11::print() 에서 파이톤과 같이 print를 할 수 있습니다.
    bool getOutputInfo(CHOP_OutputInfo* info, const OP_Inputs *inputs, void *reserved1) override
    {
    	info->numSamples = 600;
    	info->numChannels = 1;
    
    	PyObject* pyobj = inputs->getParPython("Pythonparam");
    	if (pyobj)
    	{
    		py::object o = py::object(pyobj, false);
    		py::print(o);
    	}
    
    	return true;
    }
    
    py::object(pyobj, false)같은 경우pybind11:::object 초기화 시 두 번째 파라미터를 적절하게 사용하면 메모리 유출과 붕괴를 일으킬 수 있으므로 주의해야 한다
  • 진짜 상황: C++방면에서 소유권을 가진다.불명확하게 호출.dec_ref()하지 않으면 메모리가 열리지 않습니다
  • 가짜 상황: 파이썬 측의 소유권을 참조한다.pybind 11:object가 역할 영역을 통과한 후 자동으로 열기
  • C++에서 Text DAT 함수 호출


    pybind 11의 동작을 확인한 후, C++에서Text DAT에 정의된 Python 함수를 호출해 보십시오.
    Touch Designer 측에서 ↓에서 보듯이 C++ 작업자가 정의한 Python Parametermod('text1')에 대해 호출하고자 하는 Text DAT를 모듈로 교부합니다.

    모듈로 전달되는 텍스트DAT는 일반 파이썬 대상이기 때문에 hasattr 또는 getattr로 콘텐츠에 접근할 수 있다.getattr에서 대상을 얻으면 .call()에서 함수를 호출할 수 있습니다.
    bool getOutputInfo(CHOP_OutputInfo* info, const OP_Inputs *inputs, void *reserved1) override
    {
    	info->numSamples = 600;
    	info->numChannels = 1;
    
    	PyObject* pyobj = inputs->getParPython("Pythonparam");
    	if (pyobj)
    	{
    		py::object text1 = py::object(pyobj, false);
    
    		if (!text1.is_none()
    			&& py::hasattr(text1, "td_func")) // td_func があるか確認
    		{
    			py::object td_func = py::getattr(text1, "td_func"); // td_func を取得
    			td_func.call(); // 関数呼び出し
    		}
    	}
    
    	return true;
    }
    
    Touch Designer의 Textport에 Text DAT에 적힌 print 글의 내용이 표시되면 C++→Python이 호출되었습니다

    함수 호출 매개 변수


    함수를 호출할 때 .call() 임의의 매개 변수를 추가할 수 있습니다.그때의 형전환과 번거로운 부분pybind11은 자동으로 대응한다.
    예를 들어 std:vector와 같은 stl형도 전달할 수 있다.#include <pybind11/stl.h> 몽로에 추가, 함수 호출 부분은 ↓와 같이 변경
    std::vector<float> arr{1, 2, 3, 4, 5};
    td_func.call(arr, "string");
    
    이때 호출자의 Text DAT의 Pythhon 코드도 변경됩니다.실행해 보면 파라미터가 의도대로 전달된다는 것을 알 수 있다.

    C++ 함수를 Python으로 내보내기


    그런 다음 C++ 함수를 Python으로 내보내는 방법입니다.
    대략적인 절차로 아까와 마찬가지로 Text DAT의 모듈을 진행했는데 이번에 사용py::setattr().
    그러나 Text DAT에 미리 정의된 내용만 setatter할 수 있기 때문에 Text DAT에 미리 정의된 호출 함수를 편집해야 합니다.

    다른 Text DAT를 만들고 함수를 호출하면 에 정의된 text1로 표시됩니다.다음은 이 함수를 덮어쓰는 부분을 C++ 플러그인에서 설치합니다.
    PyObject* pyobj = inputs->getParPython("Pythonparam");
    if (pyobj)
    {
    	py::object text1 = py::object(pyobj, false);
    	
    	// ...
    
    	if (!text1.is_none()
    		&& py::hasattr(text1, "cpp_func"))
    	{
    		// 複数回初期化されないためのガード
    		static bool inited = false;
    		if (!inited)
    		{
    			inited = true;
    			
    			// Pythonにエクスポートする関数を作る
    			auto fn = py::cpp_function([]() -> std::string {
    				std::cout << "C++" << std::endl;
    				return "c++ result";
    			});
    
    			py::setattr(text1, "cpp_func", fn); // cpp_func を上書き
    		}
    	}
    }
    
    여러 번 함수를 내보내는 것은 큰 의미가 없기 때문에 dummy 표시를 하고 여러 번 실행하지 않습니다.파이톤의 함수는 static bool에 함수를 전달하여 완성할 수 있다.이번에 우리는 람다식 함수를 제출했는데, 만약 pybind11::cpp_function() 로 변환할 수 있다면, 나는 무엇이든지 너에게 맡길 수 있다고 생각한다.

    아까와 마찬가지로 다른 Text DAT에서 std::function 호출되었을 때 cpp_func 인쇄가 사라졌고, 대신 되돌아오는 값 dummy 으로 되돌아왔다.
    환경 변수str로 지정하면 TouchDesigner가 시작될 때 stdout 출력 창이 표시됩니다.그곳은 설치 방식에 따라 표시되어야 한다TOUCH_TEXT_CONSOLE=1.

    총결산


    터치 디자이너에서 C++만 제공하는 프로그램 라이브러리를 사용하기 위해 반복 시험에서 발견한 방법으로, 최근에는 이보다 pybind 11과 Cython 등 패키지 C++ 프로그램 라이브러리를 사용한 파이썬 모듈을 제작했다.터치데싱어로 가져와서 사용하는 게 편할 것 같아요.
    다만, 이 수법으로만 해결할 수 있는 경우도 있기 때문에 어딘가 누군가에게 도움이 될지도 모른다는 점을 재고해 기사로 정리했다.
    터치 디자이너의 메시지인 줄 알았는데 거의 C++, cmake, 파이썬 API 이슈였는데, 터치 디자이너의 추가 달력을 기대하신 여러분께 정말 죄송합니다...완전히 ↓

    좋은 웹페이지 즐겨찾기