A few days back I had help from SO members in creating a safe plugins system, using interfaces to communicate between the main app and the dll's. This solved some problems I was having with Access Violations and memory leaks, and all is working perfectly now, without errors or crashes.
So, I've been creating some long due plugins for this project, which lead me to another problem: Speed
What I'm doing right now is, when the main app starts, loads all dll's in a specific folder that follow a determined name patern.
The code I'm using to load them is the following:
if FindFirst(cfg.ExePath+cPathPlugins+'\np*.npl', faAnyFile, SR)<>0
then Exit; // npl files are in fact renamed dll's
PluginHost := TPluginHost.Create as IPluginHost;
Plugins := TObjectList<TPluginInfo>.Create(True);
repeat
if (SR.Attr <> faDirectory)
then begin
dll := LoadLibrary(PChar(cfg.ExePath+cPathPlugins+SR.Name));
if dll<>0
then begin
#PluginInit := GetProcAddress(dll, 'PluginInitialize');
if Assigned(PluginInit)
then begin
Plugin := TPluginInfo.Create;
try
Plugin.Dll := dll;
Plugin.Intf := PluginInit(PluginHost);
Plugins.Add(Plugin);
except
Plugin.Free;
end;
end
else FreeLibrary(dll);
end;
end;
until FindNext(SR)<>0;
System.SysUtils.FindClose(SR);
This bit of code takes about 45s to load 7 plugins. None of these dll's have initialization code, and the PluginInitialize just passes the host interface and retrieves the plugin interface.
My questions are:
Can the number of methods on the interfaces affect the loading speed at this point? I don't believe so, but would like to confirm.
Could this loading time be cut somehow, while still loading them at startup?
I did thought of an alternative, having the names of the plugins to load in the database and loading the dll itself only upon first usage, but I'd prefer not to apply this, as some of these plugins must run automatically upon completion of some events during the app's execution, and not only though a menu option on demand.
I thought maybe this could be done loading the plugins in background, on a different thread, but I don't know if this could bring any risks, since I've never used threads.
I believe the main risk with using threads is when one tries to access variables that are being modified by the other, is this right?
In this case, that wouldn't happen, I think, as what comes after the plugin loading is grabing the plugins name (using one of its methods) and adding it to a TButtonGroup, that is created before starting the search for the dll's.
Do you believe this would be a good solution?
If not, any alternative you can point me to?
Your problem is that the DLL's are large. You need to create the DLL's using run time packages. That way, the code is only loaded once. Each DLL will include duplicates of the same code. LoadLibrary will load the DLL and call the initialization code for each DLL. This means that package X would be linked into each plugin that uses it and would be initialized when each plug in is loaded. (corrected)
For standalone EXE file, taking off runtime packages is great. It makes deployment much simpler. When you want to start using a plugin system, it's best to switch to a system that includes runtime packages.
That doesn't mean that you need to keep every runtime package separate. For example, if you only use Dev Express controls in the main application or in a single plugin then you can let Delphi compile that package into the App/DLL.
To change which runtime packages you wish to keep separate and which ones you wish to include in the project go to the "Packages-Runtime Packages" page in the project options. There is a check box that lets you choose to link with runtime packages. Underneath is a text box. In this text box you can specify the names of the packages that you want to keep separate.
Related
The title says it all. But, are there too many files to be replaced and is there a risk? What I mean is, there are files like d3d11.dll. Could I replace the files with with something like d3d12.dll or something like that?
When code is compiled it uses 'headers' and usually links to 'libraries' which refer to functions inside the dll. When the game loads it maps the DLL into the address space of the executable so that the program can use features in the DLL.
So if the Game does D3D11_DrawTriangles, it will end up calling that feature in d3d11.dll. Dropping in the DX12 DLL won't work because the expected function is no longer there (and besides, the executable would still be looking for the 11 DLL - it wouldn't even load).
Upgrading from DX11 to DX12 is a major undertaking; the graphics APIs are very different.
Put another way: It's like someone dropped a Fiat engine into your Volvo. Would it work? How much effort would it be to rewire all the pipes and electronics to make it work?
I am trying to load a dynamic library <libname>.so which is present in current directory as well as in /use/lib, /lib, /lib32. but program is not able to find it to any of these path.
I am running a pascal program and it has this method
LibHandle := LoadLibrary( PAnsiChar(Trim('./libtrdp.so')) );
it fails and gives error.
"This binary has no dynamic library support compiled in.
Recompile the application with a dynamic-library-driver in the program uses clause before other units using dynamic libraries.
Runtime error 235 at $0805F292"
if anyone is aware of this issue then please let me know as I have searched on the internet but could not find the answer.
Note: I am running this program on Linux machine.
Add unit dynlibs to the uses clause.
On Linux, loadlibrary is an empty stub that gets filled when you add dynlibs. This is done to keep the base runtime libc+dl free.
I am attempting to convert parts of an Android app to iOS using Doppl, and I am getting a strange result: Doppl keeps trying to pull in android.arch.lifecycle:reactivestreams, even though I don't want it to.
Specifically, in app/build/j2objcSrcGenMain/android/arch/lifecycle/, there is a reactivestrams/ subdirectory with R.h and R.m files in it. This seems to make Xcode cranky and may explain why I had some oddities with pod install.
My app/build.gradle has compile "android.arch.lifecycle:reactivestreams:$archVer", because my activity is using LiveDataReactiveStreams.fromPublisher(). However:
The activity is not in the translatePattern (and since its code is not showing up in app/build/j2objcSrcGenMain/, I have to assume that the translatePattern is fine)
I do not have a doppl statement related to reactivestreams, because there does not appear to be a Doppl conversion of this library (nor should it be needed here)
AFAIK, nowhere else in this app am I referring to LiveDataReactiveStreams, which AFAIK is the one-and-only public class from the reactivestreams library
So, the questions:
What determines whether Doppl creates R.h and R.m files for some dependency? It's not the existence of a doppl statement, as I have doppl statements for a lot of other dependencies (RxJava, RxAndroid, Retrofit) and those do not get R.h and R.m files. It's not whether the dependency is referenced from generated code, as my repository definitely uses RxJava and Retrofit, yet there are no R files for those.
How can I figure out why Doppl generates R.h and R.m for reactivestreams?
Once I get this cleared up... do I re-run pod install, or is there some other pod command to refresh an existing pod with a new implementation?
Look into 'app/build/generated/source/r/debug' and confirm there's an R.java being created for the architecture component. It'll be under 'android/arch/lifecycle/reactivestrams'.
I think there are 2 problems here.
Problem 1
Somehow Doppl/J2objc is of the opinion that this file should be transpiled. It could be either that 'translatePattern' matches with it, or that something in the shared code is referencing it. If you can't figure out which, please post a comment and I'll try to help (or post in slack group).
Problem 2
Regardless of why that 'R.java' is being sucked into the translate step, because of how stock J2objc is configured, the code is being generated with package folders instead of creating One Big Name. That generated file should be called 'AndroidArchLifecycleReactivestramsR.h' (and AndroidArchLifecycleReactivestramsR.m). Xcode really doesn't like package folders. That's why there's a slightly custom J2ojbc being used with Doppl, so we can have files with big names instead of folders.
In cases where you intentionally use package names that match with what J2objc considers to be "system" classes, you need to provide a header mapping file to force long names. The 'androidbase' doppl library needs to add a lot of files that are in the 'android' package, which J2objc considers "system". We override those names in the mapping file.
build.gradle
https://github.com/doppllib/core-doppl/blob/master/androidbase/build.gradle#L19
mapping file
https://github.com/doppllib/core-doppl/blob/master/androidbase/src/main/java/androidbase.mappings
I screwed up.
In my dopplConfig, I have:
translatePattern {
include '**/api/**'
include '**/arch/**'
include '**/RepositoryTest.java'
}
In this case, **/arch/** not only matches my arch package, but also the arch package from the Architecture Components.
Ordinarily, this would not matter, because the Architecture Components source code is not in my project. But, R.java gets generated, due to resources, and the translatePattern includes generated source code in addition to lovingly hand-crafted source code. So, that's where my extraneous Objective-C was coming from.
Many thanks to Kevin Galligan for his assistance with this, out on the #newbiehelp Doppl Slack channel!
I've written a Tcl script that uses the TclMagick extension together with GraphicsMagick.
For GraphicsMagick, I've both the Windows DLLs and the Linux SO files. I want to be able to make two Starkit/Starpack applications bundled with those libraries: one for Windows (with the DLLs) and one for Linux (with the SO files).
Is this reasonable? Can it be done?
EDIT
I cannot seem to use DLLs with dependencies under Windows. In my case, I want to use the TclMagick extension, but it needs the GraphicsMagick's DLLs and the starkit cannot find those. What should I do in this situation?
Yes. In the lib/tclmagick subdirectory of $starkit::topdir, you'll place the dynamic library and an appropriate pkgIndex.tcl file that loads the library. Use a Makefile or some other build script to use the correct dynamic library file, and generate the pkgIndex, depending the target platform.
The directory hierarchy:
appname.vfs/
main.tcl
lib/
app-appname/
appname.tcl
pkgIndex.tcl
tclmagick/
pkgIndex.tcl
tclMagick.so
package require tclmagick will work as you expect, for some capitalization of "tclmagick"
You can do it, but you might need some extra windows trickery to get things to work properly.
Windows has quite a few options to load dependent libraries, this page explains the basics:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
There are is one part that can help you:
If a DLL with the same module name is already loaded in memory, the system checks only for redirection and a manifest before resolving to the loaded DLL, no matter which directory it is in. The system does not search for the DLL.
So, to get the dependencies right, you could get the dependent libraries loaded into memory first (sadly you cannot use load for this, but could use something from twapi, e.g. twapi::load_libary (see http://wiki.tcl.tk/9886) to get the library loaded from some temporary location).
Sadly most OS's do not provide an easy or portable way to load a dynamic library directly from memory, so you need to copy the dependent libs to a temporary location first (you can do it with appropriate hacks or by using something like an installable filesystem on windows/FUSE on Linux).
In most cases the easiest route is to just link all dependencies statically into the extension instead.
I'm currently trying to load a plugin assembly dynamically in a monotouch app.
To do this, I'm referencing the plugin dll in my app project, setting the limker to 'sdk only' and then i'm trying to call Assembly.Load(filename) within my app when the plugin is required.
This is the same approach that I've previously successfully used in monodroid. However currently, this is failing in monotouch with a FileLoadException.
Is this approach possible in monotouch? Is there a special file path you need to include? Or is this not supported in the aot environment?
Note: Obviously there are other ways I can achieve a similar effect - and I do have a backup plan... but this is my preferred route (if I can make it work)
Code like:
var a = Assembly.Load ("mscorlib.dll");
Assert.NotNull (a);
works fine with both the simulator and devices. However the parameter for Load is assemblyString which is not a filename (even if the exception thrown make you think it is).
Many other overloads exists (for Load) and other methods too (e.g. LoadFrom) but they might not all work inside MonoTouch (since some runtime support might be missing).
NOTE
Handling of mscorlib.dll is special (and works in more cases than other assembles, i.e. shortcuts). However the reflection-based methods seems to work as expected in more cases, e.g.:
string filename = System.IO.Path.GetFileName (GetType ().Assembly.Location);
Assembly assembly = Assembly.ReflectionOnlyLoadFrom (filename);
Assembly.Load (or any other way of loading code dynamically) is not supported in MonoTouch.
This is an iOS restriction - all the executable code has to be in the app (and it has to be native code, which is why we use AOT to generate native code at compile time).