Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Add functions to python via C++ SDK [R20]

    Cinema 4D SDK
    c++ python
    2
    4
    1.5k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • V
      victor
      last edited by y_puech

      In the past we added Coffee functions to allow the users to make some scripts using our plugins, with the deprecation of Coffee we cannot longer support them as we did with

      *Coffee cof = GetCoffeeMaster();
      cof->AddGlobalFunction("blablabla", (V_CODE)blablabla);

      Is there any chance to add custom functions to Python in C4d?

      Thank you in advance for any help.

      1 Reply Last reply Reply Quote 0
      • Y
        y_puech
        last edited by

        Hi,

        You can add new functions with the C++ API using the Python library defined in frameworks/cinema.frameworksource/c4d_libs/lib_py.h
        This header is not documented but it allows to extend and embed Python.

        I already posted some code snippets and information in this topic.

        The posted code mostly compiles in R20 except the enumerations.

        Here's the code and corresponding files to add c4d.extendpyapi.HelloPython() Python function adapted for R20:

        extendpyapi.h

        #ifndef EXTENDPYAPI_H__
        #define EXTENDPYAPI_H__
        
        namespace extendpyapi
        {
        void InitExtendPython();
        void FreeExtendPython();
        }
        
        #endif
        

        extendpyapi.cpp

        #include "extendpyapi.h"
        
        #include "lib_py.h"
        
        namespace extendpyapi
        {
        
        // Global table of c4d.extendpyapi functions for PythonLibrary::InitModule()
        static maxon::BaseArray<PythonMethodData>* g_extendpyapi_functions = nullptr;
          
        // Prints "Hello from Python!" to the console
        static _PyObject *ExtendPyAPI_HelloPython(_PyObject *self)
        {
          PythonLibrary pylib;
          ApplicationOutput("Hello from Python!");
          return pylib.ReturnPyNone();
        }
        
        // Initializes c4d.extendpyapi module
        void InitExtendPyAPI()
        {
          PythonLibrary pylib;
        
          // Allocates c4d.extendpyapi module functions
          g_extendpyapi_functions = NewObjClear(maxon::BaseArray<PythonMethodData>);
          if (g_extendpyapi_functions == nullptr)
            return;
        
          // Initializes c4d.extendpyapi module functions
          g_extendpyapi_functions->Resize(2);
          PythonMethodData* moduleFunctions = g_extendpyapi_functions->GetFirst();
          moduleFunctions[0].Init("HelloPython", (PyFn)ExtendPyAPI_HelloPython, PYFN_FLAGS::NOARGS, "HelloPython() - Extend Python API");
          moduleFunctions[1].Init(String(), nullptr, PYFN_FLAGS::NONE, String()); // Last dummy element!
        
          // Initializes c4d.extendpyapi module
          if (pylib.InitModule("c4d.extendpyapi", moduleFunctions, "Extend Python API"))
            ApplicationOutput("\'c4d.extendpyapi\' module successfully initialized");
        }
        
        // Frees the module global function table
        void FreeExtendPyAPI()
        {
          DeleteObj(g_extendpyapi_functions);
        }
        
        }
        

        main.cpp

        #include "lib_py.h"
        
        #include "extendpyapi.h"
        
        ::Bool PluginStart()
        {
          return true;
        }
        
        void PluginEnd()
        {
        }
        
        ::Bool PluginMessage(::Int32 id, void* data)
        {
          switch (id)
          {
            case C4DPL_PYINITTYPES:
            {
              extendpyapi::InitExtendPyAPI();
              return true;
            }
        
            case C4DPL_PYFINALIZE:
            {
              extendpyapi::FreeExtendPyAPI();
              return true;
            }
        
            default: break;
          }
        
          return false;
        }
        

        Note ApplicationOutput() writes to the Default logger in the console and not the Python one.

        The use of the Python library defined in lib_py.h is not straightforward so do not hesitate to ask any question you may have.

        Former MAXON SDK Engineer

        1 Reply Last reply Reply Quote 2
        • V
          victor
          last edited by

          How could I add a string parameter to that function? I mean to ExtendPyAPI_HelloPython,

          Regards, Víctor

          1 Reply Last reply Reply Quote 0
          • Y
            y_puech
            last edited by

            Hi Víctor,

            To retrieve parameters a function must be initialized with PYFN_FLAGS::KEYWORDS. Then use pylib.ParseTupleAndKeywords() to get the value for each parameter.
            The following code shows the implementation of a function which expects a string, an integer and a float:

            static _PyObject *extendpyapi_PassParameters(_PyObject *self, _PyObject *args, _PyObject *keywords)
            {
            	PythonLibrary pylib;
            
            	String str;
            	Int32 integer = 0;
            	Float real = 0.0f;
            
            	const Char *kwlist[] = {"str", "integer", "real", nullptr};
            	if (!pylib.ParseTupleAndKeywords(args, keywords, "$if", kwlist, &str, &integer, &real))
            		return nullptr;
            
            	if (str.Content())
            		GePrint("Parameter str: " + str);
            
            	GePrint("Parameter integer: " + String::IntToString(integer));
            	GePrint("Parameter real: " + String::FloatToString(real));
            
            	return pylib.ReturnPyNone();
            }
            
            ...
            
            moduleFunctions[1].Init("PassParameters", (PyFn)extendpyapi_PassParameters, PYFN_FLAGS::KEYWORDS, "PassParameters() - Extend Python API");
            

            Former MAXON SDK Engineer

            1 Reply Last reply Reply Quote 2
            • First post
              Last post