• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
1

Possible to call / load an external DLL in GlobalSetup()?

Enthusiast ,
Dec 02, 2015 Dec 02, 2015

Copy link to clipboard

Copied

Hi Again

So, I'm needing to use a DLL provided to me by a third party.  I need to call a function from it in GlobalSetup().  I've linked the DLL (x64) correctly as Visual Studio is building the .aex just fine.  However, when I go to debug and apply the effect to a solid, for exampe, AE tells me:

After Effects error: plugin "testplug.aex" could not be loaded (126).

(48 :: 46)

Then, I click 'OK', and when I apply the effect again it gives me the following error:

After Effects error: invalid filter

(25 :: 3)

From my experience this usually means that After Effects cannot find some kind of DLL, but I might be wrong.   When this error comes up, I do see the following in Visual Studio's debug output:

First-chance exception at 0x00007FF8BB0D871C in AfterFX.exe: Microsoft C++ exception: long at memory location 0x000000000083AE78.

First-chance exception at 0x00007FF8BB0D871C in AfterFX.exe: Microsoft C++ exception: long at memory location 0x000000000083AFAC.

First-chance exception at 0x00007FF8BB0D871C in AfterFX.exe: Microsoft C++ exception: long at memory location 0x000000000083B610.

I doubt that means anything, but just thought I would share that info in case it does.

I've pinned down the problem to the first line of code that calls a function from the third-party DLL.  When I comment out that line, everything is okay, but when I uncomment it, I get the errors above.  So, my question is if there is anything I can further to do debug the DLL issue.  The DLL was just shipped with an SDK, so I don't have access to the source.

If there is any insight you all can offer, I would be most appreciative.

Thanks and best,
Arie

TOPICS
SDK

Views

1.7K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Deleted User
Dec 03, 2015 Dec 03, 2015

Any reason you are using the CS5 SDK? CS6 is a pretty good choice these days as most of the non-subscription/cloud users are using CS6, afaik. And a basic CS6 plugin will in most cases also work in AE CC.

Here is complete code to getting the plugin folder as a std::string:

#include <string>

using namespace std;

...

A_char pluginFolderPath[AEFX_MAX_PATH];

PF_GET_PLATFORM_DATA(PF_PlatData_EXE_FILE_PATH_DEPRECATED, &pluginFolderPath);

string pluginPath = string(pluginFolderPath); // contains now the full

...

Votes

Translate

Translate
Enthusiast ,
Dec 02, 2015 Dec 02, 2015

Copy link to clipboard

Copied

OMG, after debugging this for the past 24 hours, and finally posting my question here on the forum, I think I have found the answer!  If I place the third party DLL inside at this path on my system with AE installed:

C:\Program Files\Adobe\Adobe After Effects CC 2014\Support Files

Then my plugin works fine!  If I place the plugin within the Plug-ins directory or even within the Plug-ins/Effects directory, then my plugin won't load into AE. 

So, I guess my question is two-fold:  is it okay to have an installer dump a dll that my plugin needs into the '/Support Files' directory?  If not, what is the proper way of going about doing this?

Thanks,
Arie

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Dec 02, 2015 Dec 02, 2015

Copy link to clipboard

Copied

Hi Arie,

glad you found the answer yourself.

Yes, this is how Windows works! If you load a DLL from another DLL, the second DLL will be looked for in the location of the application that loaded the first DLL, NOT in the location of the first DLL itself. If it can't find the DLL there, it will look in the system path through all directories listed there. So you can either put it in "Support Files" (where the AE .exe is), which is bad practice in my opinion, or in a custom folder that you add to the path environment variable yourself (also not so nice, but done by bigger software suites), or in a subfolder of the user's OS-specific common/application/preferences/whatever folder (some plugins do that, but you have to do it in the installer and then determine that path from your plugin as well), or you put your second DLL next to your plugin DLL, then determine in your C++ code the path where your main plugin DLL resides and is loaded from (either using OS specific functions or using a built-in AE API function) and then load your second DLL using this absolute path (recommended solution).

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Dec 02, 2015 Dec 02, 2015

Copy link to clipboard

Copied

For reference, here is how getting the path to the plugin DLL can be achieved using the AE SDK:

A_UTF16Char wPath[AEFX_MAX_PATH];

PF_GET_PLATFORM_DATA (PF_PlatData_EXE_FILE_PATH_W, wPath);

You'll have to do some UTF16 juggling to get that path string into something LoadLibrary understands though, even when you use the LoadlibraryW variant.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 03, 2015 Dec 03, 2015

Copy link to clipboard

Copied

Toby,

Thanks for the code, I appreciate it.  I agree that it's bad practice to pollute AE's standard /Support File directory with a third-party dll. 

What is LoadLibrary and LoadLibraryW?  Is that some kind of standard function that is included with C++?

Also, I have some questions about the code you presented.  It look like you first declared a variable named `wPath` that is an array set to a length defined by AEFX_MAX_PATH.  Then PF_GET_PLATFORM_DATA() loads PF_PlatData_EXE_FILE_PATH into the wPath array.  Is my understanding correct?  I guess I don't understand how getting the PF_PlatData_EXE_FILE_PATH will help me in loading a DLL that exists outside of AE's application folder.

For example, I would prefer to store the third-party DLL somewhere like C:\ProgramData\AppFolder\third-party.dll.  How do I implement this in my code since, from what I understan, PF_PlatData_EXE_FILE_PATH would just give me the full path to the AfterFX.exe executable.  I'm probably misunderstanding something.

Thanks again for your time and help!

—Arie

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Dec 03, 2015 Dec 03, 2015

Copy link to clipboard

Copied

Hi Arie,

well the naming of PF_PlatData_EXE_FILE_PATH is a bit misleading, as it will actually give you the location to your plugin, not to the AfterFX.exe!

If you are not yet comfortable with widestrings/UTF16, you can also try the deprecated "char" version of it, but beware that it might not work on every system, e.g. with paths with Unicode characters in them:

A_char pluginFolderPath[AEFX_MAX_PATH];

PF_GET_PLATFORM_DATA(PF_PlatData_EXE_FILE_PATH_DEPRECATED, &pluginFolderPath);

As to why this could help: well, you need to find a place for your secondary DLL that is 1. easy to deploy to and 2. easy to determine from your first DLL.

This PF_PlatData_EXE_FILE_PATH stuff would allow you to actually deploy both DLLs to the same location, which would be easier, e.g. for writing an installer or when users are manually installing. Both DLLs would then reside in either AE's plugins directory or in the Mediacore plugin folder.

If you want to deploy your second DLL to another location, you have to make sure it is accessible for writing (when installing) and reading (when loading it). For many environments with restricted permissions that means only somewhere in the user's home directory or its subfolders.

There are some standard locations that are often used, mainly these:

On MacOS (since 10.9 or so I think): ~/Library/Application Support/[YourProductName]

On Windows:  \users\[username]\AppData\Roaming\[YourProductName]

These paths can be programmatically determined by calling the following OS-specific functions:

On MacOS: FSFindFolder(kUserDomain, kApplicationSupportFolderType, kDontCreateFolder, &fsRef);

On Windows: SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);

Of course you can choose any other path, but be advised that what works on your system does often not work on another 🙂

Concerning "LoadLibrary": that is a Microsoft-specific function from the Windows API for dynamically (i.e. at runtime) loading a DLL from a given path. "LoadLibraryW" is the Unicode/widestring version of it.

On MacOS the corresponding function is called "dlopen".

If you are however not loading the DLL at runtime but statically linking to a .lib stub (on Windows), then your options are limited anyway, as you can't influence the loading process from the code side, so you *have* to make sure in your installer that you place the DLL in a directory which is in your path folder or add a new, custom folder to your path. The standard user locations mentioned above are NOT part of the path environment/search path by default!

Sorry if this is causing you even more confusion/information overload 🙂

Cheers,

Toby

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 03, 2015 Dec 03, 2015

Copy link to clipboard

Copied

Hey Toby,

No information overload here--I appreciate as much info on this as possible!  The only information overload is when I hit up MSDN's website and read Microsoft's documentation   Your explanation is far more appreciated.

So, I realized that I'm building against CS5's SDK since I need to support that version.  I pasted in the code you offered into my source and VS2012 is telling me that PF_PlatData_EXE_FILE_PATH_W is undefined.  I took a look at CS6 SDK PDF documentation, and it does look like it's in CS6 where they introduced PF_PlatData_EXE_FILE_PATH_W.  So, I think I'll just have to do the deprecated way you mentioned and run the risk of unicode characters in paths breaking the loading of the plugin.

I think placing the secondary .dll next to my .aex which lives in a subfolder of the /Effects directory is the way I'll try for now.  If I cannot get it to load via implementation of code, I'll just dump the .dll into the /Support Files directory even though I know it's not best practice.  Oh the dilemmas we developer's face

One question I have is once I get the path from PF_GET_PLATFORM_DATA(), how do I concatenate the name of the .dll file to the character array?

Thanks again for your time and help!  I'll post an update if I can get it to work this way.

Thanks,
Arie

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Dec 03, 2015 Dec 03, 2015

Copy link to clipboard

Copied

Any reason you are using the CS5 SDK? CS6 is a pretty good choice these days as most of the non-subscription/cloud users are using CS6, afaik. And a basic CS6 plugin will in most cases also work in AE CC.

Here is complete code to getting the plugin folder as a std::string:

#include <string>

using namespace std;

...

A_char pluginFolderPath[AEFX_MAX_PATH];

PF_GET_PLATFORM_DATA(PF_PlatData_EXE_FILE_PATH_DEPRECATED, &pluginFolderPath);

string pluginPath = string(pluginFolderPath); // contains now the full path including plugin name

int pos = (int)pluginPath.find_last_of("\\/"); // find last folder delimiter

if (pos >= 0) pluginPath = pluginPath.substr(0, pos + 1); // grab anything before that

...

string myPluginPath = pluginPath + "My3rdPartyDll.dll";

HINSTANCE myDllHandle = LoadLibrary(myPluginPath.c_str());

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 03, 2015 Dec 03, 2015

Copy link to clipboard

Copied

Hey Toby,

I cannot thank you enough for your time help and sharing of this code.  I will implement and see how it goes.

Regarding your question about CS5.  I wish we didn't have to support it, but we do because our software enhances many already created After Effects projects already built in CS5.   We may drop support for it in the future, but not sure when.

Thanks again for your time, expertise, and guidance.

—Arie

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Oct 26, 2020 Oct 26, 2020

Copy link to clipboard

Copied

LATEST

Did you manage this? How you deploy .dll now in 2020? 🙂
I'm trying to make plug-in with SFML or Cairo graphic library, and they both can work statically or dynamically. So there I can put dll and use them from my plugin?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines