Custom Libraries



  • On 03/02/2014 at 08:49, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   13 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Found a small typo in the C++ docs for making custom libraries.

    Bool MyLibraryFunction(LONG v, String s)  
    {  
      MyFunctionLib* flib = CheckMyFunctionLib(LIBOFFSET(MyFunctionLib, MyLibraryFunction));  
      //if (!lfib || !flib->MyLibraryFunction) return FALSE;  //<--- typo  
      if (!flib || !flib->MyLibraryFunction) return FALSE;    //<--- Corrected  
        
      return flib->MyLibraryFunction(v, s);  
    }
    

    Also. Can I make a humble suggestion?
    You guys did a great job with the docs here by including the complete example code.
    But you don't show the user what to actually do with them. And you leave them hanging on what to do next.

    I think it would help newbies a lot if you add something to the docs indicating that you must also create a main.cpp file and compile these libraries the same way we compile any other plugins.
    I had no idea what to do with the provided code until I remembered how I wrote my CustomDataType plugins.
    If I hadn't ever built a CustomDataType plugin. I would not know what to do with your example code.

    Just a suggestion.

    -ScottA



  • On 03/02/2014 at 10:56, xxxxxxxx wrote:

    Also found some errors in the Class example.

    The class example uses: #include "mylibrary.h" which is wrong. That header file was for the previous example.
    It should be using: #include "my1dvectorlibrary.h"

    And the code example for using the class doesn't work for me.
    So I had to write it a different way:

      
    //From the docs  
      AutoAlloc<My1DVector> v;  
      v.SetReal(5.0);       //<--- Error: no such thing as SetReal in AllocType  
      
      
    //This works for me  
      AutoAlloc<My1DVector> v;  
      v->SetX(5.0);  
      Real value = v->GetX();  
      GePrint(RealToString(value));
    

    These are minor errors. But they might trip people up.
    This is the first time I've noticed that we could write our own C++ modules like this. I wonder how many people actually use it?

    -ScottA



  • On 04/02/2014 at 06:27, xxxxxxxx wrote:

    Hi,

    Thanks for pointing out these typos and errors in the "Creating Libraries" page of the C++ documentation. I'll fix them and also add explanations.
    I think the code snippet in this page should be put into an example plugin so it would show how to completely develop a custom library.

    Developing libraries is useful to reuse code between plugins.
    BTW the C++ API includes libraries for sculpting, character animation, noise, graph view (Xpresso) etc.



  • On 04/02/2014 at 08:12, xxxxxxxx wrote:

    I've created working functionlibrary & classlibray R13 plugins based on the code in the docs. And they seem to work fine.
    But I'm still wondering if I'm implementing them correctly(smartly). Or if there's maybe another possibly better way to do it?

    This is how I'm using them

    -I've got the compiled plugins in my plugins folder.

    -In my other plugins whenever I want to use these libraries. I'm adding the full path to their .h file to include them.
    Something like this: "C:\Program Files\MAXON\CINEMA 4D R13\plugins\myFunctionLibrary\source\myfunctionlibrary.h"
    So I'm pointing from one plugin in my plugins folder. To another plugin in the plugins folder.
    That feels bit strange to me. And possibly a bad practice?

    -Then I virtually load the library's .cpp file to the project. Like this: Add->Existing Item->myfunctionlibrary.cpp

    It all works. But it feels a little bit clumsy to me.
    And I can't help but feel there's maybe a better, smarter way to load these libraries into the other plugins better?

    -ScottA



  • On 04/02/2014 at 10:17, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    -I've got the compiled plugins in my plugins folder.
    -In my other plugins whenever I want to use these libraries. I'm adding the full path to their .h file to include them.
    Something like this: "C:\Program Files\MAXON\CINEMA 4D R13\plugins\myFunctionLibrary\source\myfunctionlibrary.h"
    So I'm pointing from one plugin in my plugins folder. To another plugin in the plugins folder.
    That feels bit strange to me. And possibly a bad practice?

    You should be safe using relative paths to the header files if the library is also installed in the plugins folder of CINEMA. Also, you should have your plugins installed in the user folder instead of the program folder.

    Originally posted by xxxxxxxx

    -Then I virtually load the library's .cpp file to the project. Like this: Add->Existing Item->myfunctionlibrary.cpp

    If a library is successfully installed with InstallLibrary() you can retrieve its cache and initialize it with CheckLib(). For example take a look at the code for InitThinkingParticles() in the API.
    You don't have to add the library's C++ body (cpp file) because it should have been dynamically (cdl file) loaded by CINEMA.

    I'll develop a simple library example and post it tomorrow because this isn't explained in the documentation.



  • On 04/02/2014 at 11:51, xxxxxxxx wrote:

    OK thanks.
    I can't quite figure out how to make CheckLib() work.

    Bool PluginMessage(LONG id, void *data)  
    {  
      switch (id)  
      {  
          case C4DPL_STARTACTIVITY:  
          {    
              LONG offset = LIBOFFSET(MyFunctionLib, MyLibraryFunction);   
              CheckLib(MY_UNIQUE_FUNCTION_LIBRARY_ID, offset, flib_cache); //<--Can't get the cache parameter to work  
          }  
          break;  
      
      //....
    

    I'll wait and look at your example tomorrow.
    It will probably show me what I'm doing wrong there.

    -ScottA



  • On 16/03/2014 at 03:15, xxxxxxxx wrote:

    You cast it to a C4DLibrary* pointer.

    MyLibrary* GetMyLibrary() {
        static MyLibrary* flib_cache;
        return (MyLibrary* ) CheckLib(My_UNIQUE_FUNCTION_LIBRARY_ID, offset, (C4DLibrary** ) &flib_cache);
    }
    

    Take a look at the lib_py.h header or into the many other lib_~ headers, it is used there everywhere, often
    in combination with macros to reduce the code that needs to be written.

    In case you do not already, make sure you understand the concept of function pointers.

    Best,
    -Niklas

    Edit: Fixed code



  • On 16/03/2014 at 08:36, xxxxxxxx wrote:

    Hi Niklas.

    I'm already using that same code in my: myfunctionlibrary.cpp file.
    But the problem I'm having is that I cannot use my library in another plugin unless I load that file manually using: Add->Existing Item->myfunctionlibrary.cpp

    If I don't add a virtual reference to that .cpp file manually by hand. Then the complier throws linking errors. That's the part I can't figure out.
    Yannick said he was going to create an SDK example. But then he vanished again(those damned aliens won't leave him alone 😄).
    But it's no big deal. I can wait for the next SDK update and get by with adding the reference by hand. But it would be nice to know how to  make it work without having to doing that.

    -ScottA



  • On 16/03/2014 at 13:26, xxxxxxxx wrote:

    Ah ha!
    I finally got it working.

    This probably won't make sense to anyone but me. But I'll show the code anyway.
    What I did was create a Custom Function library using the code in the R13 docs + the fixes I mentioned in my previous posts.
    I called it "MyLibraryFunction".

    It worked fine if I manually added the mylibraryfunction.cpp file to the project of the plugin I was working in. But I kept getting link errors if I tried to load it with CheckLib().
    After a lot of failures. I finally hit upon the correct syntax to load the library from within the plugin that I'm working in. Where I wanted to use my custom library.

    //To load the library inside of your plugin's code use this  
      
      MyFunctionLib *mfl = NULL;  
      LONG offset = LIBOFFSET(MyFunctionLib, MyLibraryFunction);   
      CheckLib(MY_UNIQUE_FUNCTION_LIBRARY_ID, offset, (C4DLibrary** ) &mfl);  
      
      //Now I can call to and use a function that's in my custom library like this:  
      mfl->MyLibraryFunction(10, "Hello from MyFunctionLibrary"); 
    
    //To load the custom library when your plugin loads  
    Bool PluginMessage(LONG id, void *data)  
    {  
      switch (id)  
      {  
          case C4DPL_STARTACTIVITY:  
          {    
              MyFunctionLib *mfl = NULL;  
              LONG offset = LIBOFFSET(MyFunctionLib, MyLibraryFunction);   
              CheckLib(MY_UNIQUE_FUNCTION_LIBRARY_ID, offset, (C4DLibrary** ) &mfl);  
      
              mfl->MyLibraryFunction(10, "Hello from MyFunctionLibrary");   
          }  
          break;  
      
      
      //...The other loading functions...  
      
    }  
      
    }
    

    -ScottA


Log in to reply