Plugin does not appear in Expression on client's Cinema 4D
-
@Havremunken I have a logging for a licensing system. And in the debugging we can see the process of plugin initialization (of course testing it on the developer's side).
But on my side the plugin initializes as expected.
Client has some rare problem which I cannot even understand a possible root. -
I can relate to the problem, even if I never experienced this in a Cinema 4D context. I don't know of course the technical level of your customer, but something that hopefully they are able to handle is the console inside of C4D. You can print to that using
ApplicationOutput("Some string");
- would it be an idea to compile a debug version for the customer, putting ApplicationOutput statements at various init points in the plugin, and see if these messages show up for them? Unfortunately I don't have the knowledge to look deeper at this myself. -
Hey @yaya,
Thank you for reaching out to us. A multitude of things can here be the reason, and it is hard to give good advice at a distance. When you encounter such issues, you should always use
-g_console
under Windows to get more debug information from Cinema 4D. You could do this to start Cinema 4D with that argument:When I try to load your 2025 plugin with Cinema 4D 2025.1.0 , I will get this error in said console:
WARNING: Error loading file:///D:/plugins/ragdoll_2025/ragdoll.xdl64: Could not load dll because of Could not load libcurl.dll due to Windows System Error #126: The specified module could not be found. [win_dll.cpp(333)]. Could not load libcrypto-3-x64.dll due to Windows System Error #126: The specified module could not be found. [win_dll.cpp(333)].. (file:///D:/plugins/ragdoll_2025/ragdoll.xdl64) [win_dll.cpp(450)] Cause: Windows System Error #126: The specified module could not be found. [win_dll.cpp(444)] [general.cpp(740)]
I assume your plugin tries to dynamically link against these libraries and fails to do so. The reasons could be manifold, but at least when I look into your plugin, I do not see you shipping them. Unless you try to do some fancy DLL embedding in your binary (which I am not sure to be a good idea for Cinema 4D plugins), your plugin package seems to simply miss these DLLs, as neither
libcurl.dll
norlibcrypto-3-x64.dll
are native Windows libraries.There is also a broad range of other reasons which could cause a plugin not to load, such as plugin ID collisions (two plugins use the same ID), mismatching ABI (e.g., the user is trying to load the 2024 plugin in Cinema 4D 2025.1.0), binaries with expired code signatures, illegal module IDs in the Maxon domain (e.g.,
net.maxon.myplugin
- Cinema 4D will refuse to load that), and users using pirated versions of Cinema 4D.Cheers,
Ferdinand -
@Havremunken thanks for the idea. I've sent to the customer the little debug version to check the log when the plugin are registered by Cinema 4D at a startup process. Will wait what he will answer me.
@ferdinand thank you for your answer. Yes, I use these dlls in my plugin. And yes, I've added them just in last update (which means that exactly the plugin instance with these dlls does not work on the client's side).
But what is confusing me - this absolutely the same plugin version loads on my side.
Plugin ID is unique. It did not caused any problems for years.
Sorry, I've not fully understood you: you are confirming that your Cinema 4D does not load the plugin too?
Then how it can be that the absolutely the same plugin file works on my side, but does not work on yours (and client's)?
PS. In some reason I can't perform adding of -g_console like you show. It says "the wrong folder".@ferdinand said in Plugin does not appear in Expression on client's Cinema 4D:
your plugin package seems to simply miss these DLLs, as neither libcurl.dll nor libcrypto-3-x64.dll are native Windows libraries.
I was thinking that during the build the Visual Studio will add all the required code from these dlls to a binary. So I was wrong and now have to fix it?... If yes, then what exactly should I perform?
-
I believe what Ferdinand means is that what is typical for dynamic linking means you need to include libcurl.dll and libcrypto-3-x64.dll with the distribution of your plugin. When Cinema 4D tries to initialize your plugin, it will in turn try to open these to use code from them.
I would assume that you have them on your system, which is why it works there but not for the customer.
-
Hey,
@yaya said in Plugin does not appear in Expression on client's Cinema 4D:
But what is confusing me - this absolutely the same plugin version loads on my side [...] I was thinking that during the build the Visual Studio will add all the required code from these dlls to a binary. So I was wrong and now have to fix it?... If yes, then what exactly should I perform?
Applications can use external libraries in two major ways: static and dynamic linking. This is a concept that exists independently of operating systems and there are other ways to have two binaries exchange data such as server-client communication via sockets, but static and dynamic linking are fundamental concepts.
- Static Linking: Here a linking application literally includes parts of the linked library in its own binary output. This happens at compile time and you do not have to ship the statically linked library with your app, as the relevant data is literally compiled into your app. The common file extensions for static libraries are
*.lib
(Win) and*.a
(macOS/Linux). - Dynamic Linking: Here the linking application attaches to the library binary at runtime. When the shared library you want to link against is not part of the standard library of the OS you ship for, you must ship it with your app, as the OS otherwise wont be able to find and link the library. Common extensions for dynamic/shared libraries are
*.dll
(Win),*.dylib
(macOS),*.so
(Linux).ΒΉ
A Cinema 4D plugin project can use both static and dynamic libraries. My console output implies that you used two DLLs here, the popular
libcurl
andlibcrypto
libraries. I do not have these installed on my system and you do not ship them with your plugin. Your plugin therefore cannot work on my machine as the dynamic loader of Windows won't be able to find them. But on your machine it will, since you have these files. How shared library discovery works depends on the OS (for Win see: Dynamic-link library search order). For Cinema 4D plugins it is customary to ship dynamic libraries in ares/libs
folder, e.g.,ragdoll_2025/res/libs/libcurl.dll
. But there is nothing which forces you to put them there, as library discovery is automated.What I was talking about above, is the a bit hacky technique to embed a DLL within its host application, i.e., to treat it in a certain way as a static library. I first of all never have done this myself, and I think you might run into problems with this in Cinema 4D, due to how its linking works.
Cheers,
Ferdinand1 - On Windows, the frameworks of a Cinema 4D plugin project are for example each compiled in a static
lib
library, e.g.,asset.framework.lib
. When you look into your build folder, you will find them. Your plugin will then statically link against these libraries, i.e., compile their content into itself, e.g., the fileragdoll_2025.xdl64
. Cinema 4D will then load, i.e., dynamically link against, these plugin libraries when it is booting. But Cinema 4D uses custom linking which for example bypasses the link loader on Windows. It instead has its own function pointer alignment, which causes the plugins to call the 'right' things in the Cinema 4D binaries. One could therefore say that Cinema 4D plugin libraries are a mix of static and dynamic linking, hence the custom namexdl64
on Windows (and similar deviations on other OS's). - Static Linking: Here a linking application literally includes parts of the linked library in its own binary output. This happens at compile time and you do not have to ship the statically linked library with your app, as the relevant data is literally compiled into your app. The common file extensions for static libraries are
-
@ferdinand hmm, now I think I understand.
Actually I had a problem last week with including these libcurl.dll and libcrypto-3-x64.dll into my VS2019 project. Even adding these .lib linking into the additional lib derectories and additional dependancies, I think I got the same error you quote above : Could not load libcurl.dll, libcrypto-3-x64.dll.
And only the manually adding these tow dlls into Windows/System32 fixed that problems.So now after your explanation I understand that I did not make everything correctly.
The question is now: how to properly add the
\curl_x64-windows\debug\lib
\openssl_x64-windows\debug\lib
libcurl-d.lib
libcrypto.lib
into a project (do not shipping the exact .dlls with a plugin to clients)?... -
Hey @yaya,
first of all, I must remind you of our support rules:
- We cannot provide support for third party libraries.
- We cannot debug your code for you and instead provide answers to specific problems.
The files you list there are all static libraries, at least when judging them by their extension
*.lib
. You would not have to ship them, as they are compiled into your app. Cinema 4D complains about missing dynamic libraries, e.g.,libcurl.dll
, heavily implying that your plugin tries to dynamically link against something.The very popular
libcurl
library is offered in more flavors than there are atoms in the universe. I have no idea which one you used and what its details are. There are both statically and dynamically linking versions oflibcurl
. I cannot help you much with third party libraries and how to use them.If I were you, I would do this:
- Search for the two DLLs
libcurl.dll
andlibcrypto-3-x64.dll
on your system. - When you find them (and make sure to find all of them) note down the path where you found them, and rename the files, changing both extension and name, e.g.,
libcurl.dll -> foo.bar
. I think this should be enough to hide them from the link loader of Windows (but I am not 100% sure). - Reboot your OS.
- Boot Cinema 4D with
-g_console
, you should now see the same error as shown above. - Throw the two DLL into your plugin folder, e.g., into
res/libs
and boot again. Your plugin should work again. - Reestablish the DLLs in the paths where you found them, because when they are on your machine, there is a good chance some app is using them and might require exactly that version placed in that path.
Cheers,
FerdinandPS: When you still run into issues, please show us
projectdefintion.txt
of your project (the one from the module, e.g.,root/plugins/ragdoll-plugin/project/projectdefintion.txt
). -
PS: Also try placing the DLLs in the root of your plugin folder, e.g.,
ragdoll_2025/libcurl.dll
right next to theragdoll_2025.xdl64
, as I am not sure if you need extra settings for theres/libs
path to work. -
Hmm, after delete libcurl.dll, libcrypto-3-x64.dll, libcurl-d.dll from Windows/System32 I can't reproduce the problem on my side ("Error loading file:// Could not load libcurl.dll ...Could not load libcrypto-3-x64.dll"). The plugin still loads...
I understand that it is my problem, and you do not provide help with 3rd party libraries.
Just was dreaming that I will fix everything quickly.
Just delete libcurl.dll, libcrypto-3-x64.dll, libcurl-d.dll from Windows/System32 (where I've put them before), check if the same problem appears (the plugin does not loading), then put these files into res/libs.
But it turned out that I delete files, but the plugin still loadsI'll dig further...
-
Actually I am not fully correct: the plugin now does not loading in C4D r23 and C4D 2024. But still appears in C4D 2025
Frustrating... -
One thing you could do is run a utility like procmon: https://learn.microsoft.com/en-us/sysinternals/downloads/procmon
This will let you see what a process accesses on the file system, among other things. Hopefully it will also show you which paths are searched for these libraries, allowing you to identify how to get them in the right location for your customer.
-
Hey @yaya,
When it still works, you likely missed some files somewhere. In the end you yourself can only untangle this, as we have no idea what you did there. I had a brief look at the main lib-curl project (there are many-many deviations), and what stands out, is that you also seem to have linked against the wrong library, at least judging by the main project.
[...] Could not load libcurl.dll due to Windows System Error #126 [...]
64 bit curl:
32 bit curl:
I.e., you seem to have linked against 32 bit curl, at least when judging by the name. This should not work in the first place, as Cinema 4D is a 64bit app, it cannot link against 32 bit DLLs (without getting very creative). What @Havremunken said would be the next logical step, use some of the debugging tools that come with Visual Studio. But it is of course not so good when you have to start reverse engineering your own app like that.
I assume you are all testing this on your development machine? I would recommend testing this on another machine, where you can be sure that it has not been 'tainted' with libcurl and other library fragments. When it still loads for you on such vanilla machine for you, than you have a real mystery on your hand, and have to start digging around deeper with some debug tools, to not only see what is failing (e.g., what is printed in the
-g_console
) but also which DLL access might succeed.Cheers,
Ferdinand -
I've managed to reproduce the problem: the Cinema does not load the plugin (r23 and 2025).
To do it, I not only deleted libcurl.dll, libcrypto-3-x64.dll, libcurl-d.dll from Windows/System32. It was enough for r23. For 2025 I was needed also to delete the variable from a PATH to Windows/System32.
Then I've tried to build the static lib of curl. I was thinking that this way will be better. I will not explain all the details, but it didn't - it just finished every build with:1>LINK : fatal error LNK1104: cannot open file 'curl/libcurl_a_debug.lib'.
And nothing helped to fix that.
So I decided to return to the dynamic libraries. Actually I do not mind to supply the above dlls with my plugin.
I have reverted the binding to the dynamic version of curl and openSSL. Also I have added libcurl.dll, libcrypto-3-x64.dll, libcurl-d.dll to *plugin root/res/libs (not so hoping plugin will start to take them from there).
And I've delete the variable from a PATH (Windows/System32) to make sure it won't catch on these dlls from the System32.
Now I am making the build and it finishes with the success. And when I am starting the r23 - of course there is no plugin.
Yes, -g_console says:WARNING: Error loading file:///H:/Code/r23/sdk/plugins/firstplugin/ragdoll.xdl64: Could not load dll because of Could not load libcrypto-3-x64.dll due to Windows System Error #126: The specified module could not be found. [win_dll.cpp(304)]. Could not load libcurl-d.dll due to Windows System Error #126: The specified module could not be found. [win_dll.cpp(304)].. (file:///H:/Code/r23/sdk/plugins/firstplugin/ragdoll.xdl64) [win_dll.cpp(324)] Cause: Windows System Error #126: The specified module could not be found. [win_dll.cpp(318)] [general.cpp(401)]
Expected. The same problem which clients have.
(And yes, if I will back libcurl.dll, libcrypto-3-x64.dll, libcurl-d.dll to the System32, then my plugin appears in Expression)So right now I need somehow to fix it so the plugin catch on libcurl.dll, libcrypto-3-x64.dll, libcurl-d.dll not from my Windows/System32 but from *res/libs.
How to do it?
DeepSeek gives me a hint that I can usevoid SetDllSearchPath() { // Set the DLL search path to the res/libs folder SetDllDirectory(L"res\\libs"); } // Call this function during plugin initialization SetDllSearchPath();
But I am not sure is it right?
If it is not, then how to achieve this with maybe the other correct way? -
Hey @yaya,
good to see that you made progress. To link against a static library, you can either set the respective Visual Studio module properties manually (not recommended) or set the relevant arguments in the
projectdefitnion.txt
of your module. For what you are doing, this could look something like this (for Windows), assumingcurl
would be situated in your project root, i.e., two folders "up".AdditionalLibraryDirectories.Win64.Debug =../../curl/bin/ AdditionalDependencies.Win64.Debug =libcurl_a_debug.lib AdditionalIncludeDirectories=../../curl/include
FYI, you should not ship plugins using debug libraries, as they tend to be much-much slower than release code, due to all the debug symbols and other crap floating around in them, causing performance penalties of 10x, 20x, or even more.
Cheers,
Ferdinand -
@ferdinand Yes, I will not ship the debug version of dlls. It is just for testing.
But are you sure that your that you wrote me right? Your hint is about the linking of static library but libcurl_a_debug.lib does not work for me.
Or did you mean that if I do as you described above it, the error 1>LINK : fatal error LNK1104: cannot open file 'curl/libcurl_a_debug.lib'. - will disappear? Then thank you about this solution, in this case I will need to get back again to a static library (which I already have deleted)
But what about the linking dlls to make libcurl.dll, libcrypto-3-x64.dll, libcurl-d.dll linked from res/libs during Cinema 4D startup (and for shipping first two to clients)? Is there some option for this? -
Well, I answered this:
1>LINK : fatal error LNK1104: cannot open file 'curl/libcurl_a_debug.lib'.
Which is a linker error (the static linker at compile time), where the linker cannot find the static library (libcurl_a_debug.lib) to link against. I am quite frankly a bit in the unclear what you are trying to do exactly, use the statically or the dynamically linked version of your libraries. When you "just" want to load a DLL under Windows, you could do something like this:
#include <windows.h> #include <iostream> typedef void (*MyFunctionType)(); int main() { // Load the DLL HMODULE hModule = LoadLibrary(L"MyLibrary.dll"); if (!hModule) { std::cerr << "Failed to load MyLibrary.dll" << std::endl; return 1; } // Get the function address MyFunctionType MyFunction = (MyFunctionType)GetProcAddress(hModule, "MyFunction"); if (!MyFunction) { std::cerr << "Failed to get the function address" << std::endl; FreeLibrary(hModule); return 1; } // Call the function MyFunction(); // Free the DLL FreeLibrary(hModule); return 0; }
But doing all this low-level boilerplate code poking around has become somewhat unfashionable. And Visual Studio DLL projects or third party libraries usually offer two files when creating/shipping shared libraries. The actual shared library, e.g.,
MyLibrary.dll
, and a static library fileMyLibrary.lib
which does not hold a static version of the library but the boilerplate code to correctly load that shared library at runtime and align the function/type pointers with symbols.So, even when you dynamically link against a shared library at runtime, you often link statically against a library at compile time, which takes care of the runtime boilerplate code for you. What is the case for the libraries you used there, I have no idea. The settings in the
projectdefinition.txt
are just for static linking, as linkers/compilers do not care about dynamic linking.Cheers,
Ferdinand -
@ferdinand thank you for you answer.
I was thinking that:- if at the beginning (when I just started to add the curl and openSSL to a code) the code in the VS 2019 worked fine. But after making a build the plugin does not loaded in Cinema, throwing an error about missing dlls.
But, if I managed to fix it just via:
- adding few dlls (libcurl.dll, libcrypto-3-x64.dll, libcurl-d.dll)
- to Windows/System32 and by editing system variables...
...But in this case the plugin does not work on the client's side, because of:
- clients do not have that dlls on their side,
Then:
- I can "simply" make the plugin work on the client's side just (somehow) adding missing dlls => to a plugin's res/libs and shipping them with the plugin.
I was thinking it is easy to do. But if you say that it is not (or as I understand), then I will try your solution. Which seems harder for me because my lack of knowledges.
F.e. I did not understood how to set up an exact path in the projectdefitnion.txt via that command. If f.e. I have this text in the projectdefitnion.txt:Platform=Win64;OSX Type=Solution Solution=\ plugins/cinema4dsdk;\ plugins/maxonsdk.module;\ plugins/microsdk;\ plugins/ragdoll
where the last line means the root folder of my plugin.
And if I need to include "curl" folder via your line:AdditionalLibraryDirectories.Win64.Debug =../../curl AdditionalDependencies.Win64.Debug =libcurl_a_debug.lib AdditionalIncludeDirectories=../../curl
where "curl" is a folder exactly in "ragdoll" and the "libcurl_a_debug.lib" is a file directly in the "curl"
So how to edit the line accordingly? I mean all that "../..." :AdditionalLibraryDirectories.Win64.Debug =../../curl
-
This:
Platform=Win64;OSX Type=Solution Solution=\ plugins/cinema4dsdk;\ plugins/maxonsdk.module;\ plugins/microsdk;\ plugins/ragdoll
is the
projectdefitnion.txt
of your solution, i.e., the build config which links all modules together. You must useplugins/ragdoll/project/projectdefitnion.txt
instead, it is the build config for that module. Think of it as theCMakeLists.txt
of that module when you are familiar with CMake. After these changes you must regenerate your project with the project tool.I quite frankly do not understand your solution, but as always, whatever works, works. So, if it does work for you, I am happy.
The
".."
in paths is common relative path syntax and means one folder up (in relation to the module). So,../../foo
means afoo
folder in the root of your project.root foo plugins ragdoll
Cheers,
Ferdinand -
I know what is projectdefitnion.txt. I just do not understand how to use the line: AdditionalLibraryDirectories.Win64.Debug =../../curl
And do I need to launch again the buildsdk23.bat right after each time I change this file.
I have not added the static curl library in my project yet.