PDA

View Full Version : Loading External .dll into AviSynth (LoadDll Plugin Inside)


3ngel
9th December 2006, 12:11
Hi,
i don't know if this function is already present and i'm not aware of it.
There is a way to load a /system32 .dll directly into .avs without having to put them in the above directory?
Some plugins need external dll to be present in /system32.
There is a way to load them like simple plugins, so they can be stored in other directories other than /system32?
Thanks

UPDATE:
Thank to tsp there is now a plugin "LoadDll" you can download here (http://www.avisynth.org/tsp/LoadDll.zip)

Fizick
9th December 2006, 12:15
you can put DLL (not plugin) to any folder, if you add this folder to Path in Windows setting.

3ngel
9th December 2006, 12:16
I would like a solution Windows independent like

LoadSystemDll("Path/Test.dll")
LoadPlugin("PluginThatNeedSystem32dll")

EDIT: In this way you can do simple Autoloading packages with those plugin who requires many external .dlls installed.

Fizick
9th December 2006, 13:06
system DLL is used (called) not by Avisynth but by specific plugin directly.

3ngel
9th December 2006, 13:08
But avisynth could do a wrapping method so when the plugin calls the .dll the dll is already in memory (loaded by avisynth with the previous LoadSystemDll)

Fizick
9th December 2006, 14:24
probably in some other world it could be done so way,
but in our case in existed avisynth and plugins it is implemented differently. (they all must be edited and recompiled).

can you live without it? :)

3ngel
9th December 2006, 14:28
Eheh, ok i can live without it (*sigh*)

:)

foxyshadis
11th December 2006, 01:24
Not implicitly! If you take them off, all the sudden half your tools won't start. (THANKS A LOT LEADTOOLS. Stupid broken installers.)

setarip_old
11th December 2006, 07:09
@3ngel

Assuming you have placed the .DLL in your "AVISYNTH" folder, try typing the following line from the "Run" box (available by clicking on the Windows "Start" radiobutton:

c:\windows\system\regsvr32 C:\AVISYNTH\system32.dll (Note the SPACE after "regsvr32")

foxyshadis
11th December 2006, 08:10
That'll only work on win9x (on nt it's in system32), but since it's on the path using just "regsvr32" works. But here, he's trying to use a standard dll, not a COM server, so loadlibrary won't pick it up even if it does register.

It's possible to read the registry to find the avisynth plugin folder, but there's no requirement for it to be there, so... best to use Ian's solution.

3ngel
11th December 2006, 08:30
@IanB
but SetWorkingDir() is a avisynth command? (in the case i'll try)

Next i would like to do a simple observation. I don't know in what lang avisynth is written, but in C++ there is a simple LoadLib() that load a .dll in memory.
I don't think is so complicated to wrap the function in a object (assuming is C++) that load a .dll in memory with a "Global Scope" in order to be visible by the plugin called next.
At the end of the script there would be (obviously) another function to unload the .dll from memory UnloadSystemDll()
Is so complicated?

EDIT: In case the plugins are mapped as "out of process" threads you could implement a wide-system hooking technique as explained here (http://www.codeproject.com/system/hooksys.asp).

3ngel
11th December 2006, 12:06
Either install the support .DLL's in the same directory as the Plugin
The point is that some badly written plugins, dumbly look for .dlls only in system32 directory, and not in current dir.
In the late case there would be no problem at all :)

I don't see that it a job for Avisynth to preload arbitary .DLL's.
I disagree on this point, 'cause being Avisynth the "server environment" it has do make available all the instruments to make "client plugins" works in an optimal (including a portable) way. And this includes the possibility to make available to the plugins, external (or even why not modified or optimized) system dlls.

3ngel
11th December 2006, 13:18
@IanB
Mine was not a critic, obviously, i was just politely discussing :)
I didn't want to put the "problem" on you, i was just showing a situation that can happen.
From a user point of view, i am not able to fix the dumb plugin so i expect a little help from the server.
The problem is exactly the opposite: the needed library are not static linked.
Honestly i don't see all this risk.
When a plugin requires external.dll and it's badly written, and it doesnt' find in memory, nor system32 dir, the only thing Avysinth would do is only Preload the needed library (that i specify) in memory, so instead of looking for the disklibrary it finds already in memory. It doesn't involve knowing the name of the functions.
In the specific situation, one of is fft3dfilter that requires fftw3.dll to be put forcefully in system32 (it doesn't work in current dir).

foxyshadis
11th December 2006, 14:03
Ah, but that's because avisynth plugin folder isn't the current working directory, it's the host's. If you put it in virtualdub's folder, and load the script in vdub, it'll load it just fine. (Unless you modified a shortcut to vdub to point to another folder as the cwd, which is one way around all this. But then I think vdub itself wouldn't be too happy.)

Fizick
13th December 2006, 21:45
i get this message private from 3ngel, but it is not private.

... i thougt that fftw3.dll was called by your plugin fft3dfilter.dll and so i wasn't able to explain myself why fftw3.dll was not autodownloaded being in the same dir as fft3dfilter.dll. According to Loadlibrary() specification (and my knowledge) among many places to search there is with no doubt current dir. For this reason i asked you to fix the "bug" 'cause i thought you used absolute path.
But now i realized fftw3.dll is called by avisinth itself, infact if i put the fftw3.dll in the same dire as the .avs the library is downloaded.
...


1. fftw3.dll is called not by avisynth itself, but my plugin via LoadLibrary("fftw3.dll").
2. But current path for DLL search is not your the avs dir, but folder of host application (virtualdub or other), that loads the avisynth.

3ngel
14th December 2006, 15:55
and manually lookin the same folder as fft3dfilter.dll was loaded from if the first LoadLibrary fails

I had not the "courage" to ask for that, having had the impression Fizick was a little "upsettable" when talking about his plugin, but it would be great if this addition would be made :)

Fizick
14th December 2006, 18:56
Put non-plugin DLL at plugin folder is (was ?) bad practice.

3ngel
14th December 2006, 19:02
I don't understand why you say this.
Putting dll in plugin folder makes it much more simple for plugins to work, and obviously totally portable.

tsp
14th December 2006, 19:05
if you put a non-avisynth plugin dll in the avisynth autoload folder avisynth will waste a small amount of time figuring out that the dll is not a plugin when the script is loaded.

3ngel
14th December 2006, 19:07
We are not talking about autoloading folder, but in separate dir (that is external plugin dir).

Fizick
17th December 2006, 01:39
I would encourage all users to read the plugin docs. :)

3ngel
17th December 2006, 06:04
And i dont' understand what does it cost you to add 3 rows of code as a
// Approx code
if(!Loadlibrary("fftw3.dll"))
{
path=Getcwd()
or
path=GetDllDirectory()
Loadlibrary(path + "fftw3.dll"))
}

// Second example
Path=SetDllDirectory(Getcwd())
or
Path=SetDllDirectory(GetDllDirectory())

Fizick
17th December 2006, 10:26
Why stop here?
Lets search all user hard disk for the DLL, them CDROM, floppy.
Not found? Lets repeat full disks search for all Zip archives, and automatically unpack the Dll.
Not found? Lets connent to Internet, automatically download and install DLL.
Not found? Lets make automatical call to authors phone.
Not help? RTFM at last.
;)

3ngel
17th December 2006, 10:30
Don't say nonsense.
I think it's a minimum for a plugin to search in its own folder!

PS: If my code doesn't work and Getcwd() returns Avisynth dir, then IanB code sure will do.

3ngel
17th December 2006, 13:26
@3ngel, Please don't get bent out of shape, it does not help.
Oh, really? Pheraps i've not undestood well, but I thought, seeing the code that you've got the dirpath of the plugin .dll starting from its memory address, and then use that dirpath to load the fftw3.dll (same path).

You have asked for something that actually requires a fair amount of thought and trickery to correctly and portably implement.
I don't think at all. I want only that a .dll load another .dll (that is located in /thesamediroftheplugin/whatihavetowritenowidontknow instead of /system32) and use it. I don't think it's so complicated.

The most simple way would be the first i said, that it was avisynth that load the library (through a custom external command LoadExternalDll("path")). At this point having already loaded the library (fftw3.dll) the next plugin requiring it, when it does the loadlibrary it doesn't search in the PATH 'cause it's already available in memory, loaded by avisynth.
At the end of the script there would be a freeing command
UnloadExternalLibraries("Path")
or better
UnloadExternalLibraries() with an internal implemented stack that automatically unload all the library references in the stack.
Better again
....
There is no need for a function. Avisynth automatically call at the end of the script UnloadExternalLibraries() to unload the (eventually) loaded library
It seem to you so complicated (even from an avisynth point of view)?

tsp
17th December 2006, 14:06
3ngel of this 3 solution to your problem with of them seems to be the best?
1) require every user of a filter that needs to load a dll to use a LoadExternalDll command before calling the filter and at the same time requires the developer of avisynth to add the necessary code to the next version and at the same time figure out a way to let the filters get the required handles to the loaded dll. This will also require that the filters to be rewritten and compiled to support this (and it will only work with the new version on avisynth).
2) the filter developer just copy paste the code that Ian provide and include it in the next version of their filter (or the user that really needs this downloads microsoft visual c++ express (http://msdn.microsoft.com/vstudio/express/visualc/download/) and make the change themselves)
3) the user copies the external dll to a directory in the PATH (like windows\system32) or modify the PATH so that the plugin directory is included

3ngel
17th December 2006, 15:16
Personally for me, 2 could be the best (filter developer willingly). Number 1 could also be good because
same time figure out a way to let the filters get the required handles to the loaded dll
there is no need to pass a handler to the filter. The filters doesn't need any modification because when avisynth load the library the entire library stays in memory. When the plugin call LoadLibrary("") windows get the library from memory (that is a private copy of the library loaded previously by avisynth).

tsp
17th December 2006, 15:32
Personally for me, 2 could be the best (filter developer willingly). Number 1 could also be good because

there is no need to pass a handler to the filter. The filters doesn't need any modification because when avisynth load the library the entire library stays in memory. When the plugin call LoadLibrary("") windows get the library from memory (that is a private copy of the library loaded previously by avisynth).
hmm seems you are right about that. I will create the filter for you tomorrow when I get home from work.

tsp
18th December 2006, 09:41
sorry 3ngel it was very easy to create the filter (about 20 minutes) . You can download it here (http://www.avisynth.org/tsp/LoadDll.zip).

The only reason not to add it to avisynth was that not many will need it so it may just clutter up the number of built in functions

here is the sourcecode for the filter:

// LoadDll
// Copyright(C)2006 Tonny Petersen (tsp@person.dk)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
// http://www.gnu.org/copyleft/gpl.html .

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include "avisynth.h"

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

void __cdecl UnloadDll(void* hinst,IScriptEnvironment* env)
{
if(hinst)
FreeLibrary(static_cast<HMODULE>(hinst));
}

AVSValue __cdecl LoadDll(AVSValue args, void* user_data, IScriptEnvironment* env){
HMODULE hinst=0;
hinst=LoadLibrary(args[0].AsString());
env->AtExit(UnloadDll,hinst);
return hinst!=NULL;
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("loaddll", "s", LoadDll, 0);
return "loaddll 1.0";
}

3ngel
18th December 2006, 10:53
Fantastic tsp, it works great!

Thank you so much! :cool:

It wasn't so complicated, nč IanB? :p (joking eh thanks for you precious code)

One question tsp,
what happen if i call 2 times the loadll?
I see you do a FreeLibrary() only for one instance.
On the second instance what happens?
Are two separate instances of Loaddll created (so each one frees its own library) or there is one .dll that remains in memory? (i don't know the functioning of avisynth environment)

EDIT: I put the link on the first post.

tsp
18th December 2006, 11:20
if you have this script:

loaddll(c:\fftw3.dll")
loaddll(c:\fftw3.dll")
blackness().converttoyv12()
fft3dfilter()

the first instance of loaddll loads fft3w.dll into memory and increases the reference count of fftw3 library to 1 (or rather loadlibrary does that)
the next instance of loaddll increases the reference count to 2(as the dll is already loaded)
and finally fft3dfilter increases the reference count to 3
when the script is closed first fft3dfilter is destroyed. This decreases the reference count to 2 (this happends when it calls freelibrary)
next avisynth calls UnloadDll from the second instance of loadDll that calls freelibrary that decreases the reference count to 1
and finally avisynth runs the first instance UnloadDll and the reference count decreases to 0 and fftw.dll is unloaded from memory.

3ngel
18th December 2006, 11:24
I see.

CoRoNe
27th July 2014, 14:03
Because tsp's last activity was on 1st May 2009 and because avisynth.org has moved to avisynth.nl, his filters are now to be found here (http://www.avisynth.nl/users/tsp/) and LoadDll you can download here (http://www.avisynth.nl/users/tsp/LoadDll.zip).
--------------------------------

BassAudioSource_test.avs:
LoadDll("D:\tak_deco_lib.dll")
BassAudioSource("sample(2ch).tak")
http://www.ld-host.de/uploads/images/8763e0e42005b0721645a68c1705b11c.png

Playing AviSynth-scripts (with LoadDll) in MPC-HC has never been a problem, but recently I noticed that, unlike with MPC-HC, the above error-message pops up while opening avs-files with ffmpeg.exe, ffplay.exe and avs2pipemod.exe as well.
This error always pops up, whatever the map LoadDll is pointing to (even the most simple one, D:\), with the exception of AviSynth's plugin-map.
It's not a usage blocking issue though, because ffmpeg.exe, ffplay.exe and avs2pipemod.exe appear to continue/work normally after that, but it is annoying.
Does someone with coding experience know how to easily fix this in LoadDll?