Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3948438
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 20, 20262026-05-20T01:22:28+00:00 2026-05-20T01:22:28+00:00

Context: I converted a legacy standalone engine into a plugin component for a composition

  • 0

Context: I converted a legacy standalone engine into a plugin component for a composition tool. Technically, this means that I compiled the engine code base to a C DLL which I invoke from a .NET wrapper using P/Invoke; the wrapper implements an interface defined by the composition tool. This works quite well, but now I receive the request to load multiple instances of the engine, for different projects. Since the engine keeps the project data in a set of global variables, and since the DLL with the engine code base is loaded only once, loading multiple projects means that the project data is overwritten.

I can see a number of solutions, but they all have some disadvantages:

  1. You can create multiple DLLs with the same code, which are seen as different DLLs by Windows, so their code is not shared. Probably this already works if you have multiple copies of the engine DLL with different names. However, the engine is invoked from the wrapper using DllImport attributes and I think the name of the engine DLL needs to be known when compiling the wrapper. Obviously, if I have to compile different versions of the wrapper for each project, this is quite cumbersome.

  2. The engine could run as a separate process. This means that the wrapper would launch a separate process for the engine when it loads a project, and it would use some form of IPC to communicate with this process. While this is a relatively clean solution, it requires some effort to get working, I don’t now which IPC technology would be best to set-up this kind of construction. There may also be a significant overhead of the communication: the engine needs to frequently exchange arrays of floating-point numbers.

  3. The engine could be adapted to support multiple projects. This means that the global variables should be put into a project structure, and every reference to the globals should be converted to a corresponding reference that is relative to a particular project. There are about 20-30 global variables, but as you can imagine, these global variables are referenced from all over the code base, so this conversion would need to be done in some automatic manner. A related problem is that you should be able to reference the “current” project structure in all places, but passing this along as an extra argument in each and every function signature is also cumbersome. Does there exist a technique (in C) to consider the current call stack and find the nearest enclosing instance of a relevant data value there?

Can the stackoverflow community give some advice on these (or other) solutions?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-20T01:22:29+00:00Added an answer on May 20, 2026 at 1:22 am

    Although I received a lot of answers that suggested to go for solution 3, and although I agree it’s a better solution conceptually, I think there was no way to realize that solution practically and reliably under my constraints.

    Instead, what I actually implemented was a variation of solution #1. Although the DLL name in DLLImport needs to be a compile-time constant, this question explains how to do it dynamically.

    If my code before looked like this:

    using System.Runtime.InteropServices;
    
    class DotNetAccess {
        [DllImport("mylib.dll", EntryPoint="GetVersion")]
        private static extern int _getVersion();
    
        public int GetVersion()
        {
            return _getVersion();
            //May include error handling
        }
    }
    

    It now looks like this:

    using System.IO;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using Assembly = System.Reflection.Assembly;
    
    class DotNetAccess: IDisposable {
        [DllImport("kernel32.dll", EntryPoint="LoadLibrary", SetLastError=true)]
        private static extern IntPtr _loadLibrary(string name);
        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary", SetLastError = true)]
        private static extern bool _freeLibrary(IntPtr hModule);
        [DllImport("kernel32.dll", EntryPoint="GetProcAddress", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
        private static extern IntPtr _getProcAddress(IntPtr hModule, string name);
    
        private static IntPtr LoadLibrary(string name)
        {
            IntPtr dllHandle = _loadLibrary(name);
            if (dllHandle == IntPtr.Zero)
                throw new Win32Exception();
            return dllHandle;
        }
    
        private static void FreeLibrary(IntPtr hModule)
        {
            if (!_freeLibrary(hModule))
                throw new Win32Exception();
        }
    
        private static D GetProcEntryDelegate<D>(IntPtr hModule, string name)
            where D: class
        {
            IntPtr addr = _getProcAddress(hModule, name);
            if (addr == IntPtr.Zero)
                throw new Win32Exception();
            return Marshal.GetDelegateForFunctionPointer(addr, typeof(D)) as D;
        }
    
        private string dllPath;
        private IntPtr dllHandle;
    
        public DotNetAccess()
        {
            string dllDir = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
            string origDllPath = Path.Combine(dllDir, "mylib.dll");
            if (!File.Exists(origDllPath))
                throw new Exception("MyLib DLL not found");
    
            string myDllPath = Path.Combine(dllDir, String.Format("mylib-{0}.dll", GetHashCode()));
            File.Copy(origDllPath, myDllPath);
            dllPath = myDllPath;
    
            dllHandle = LoadLibrary(dllPath);
            _getVersion = GetProcEntryDelegate<_getVersionDelegate>(dllHandle, "GetVersion");
        }
    
        public void Dispose()
        {
            if (dllHandle != IntPtr.Zero)
            {
                FreeLibrary(dllHandle);
                dllHandle = IntPtr.Zero;
            }
            if (dllPath != null)
            {
                File.Delete(dllPath);
                dllPath = null;
            }
        }
    
        private delegate int _getVersionDelegate();
        private readonly _getVersionDelegate _getVersion;
    
        public int GetVersion()
        {
            return _getVersion();
            //May include error handling
        }
    
    }
    

    Phew.

    This may seem extremely complex if you see the two versions next to each other, but once you’ve set up the infrastructure, it is a very systematic change. And more importantly, it localizes the modification in my DotNetAccess layer, which means that I don’t have to do modifications scattered all over a very large code base that is not my own.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Context: I have a WPF App that uses certain unmanaged DLLs in the D:\WordAutomation\MyApp_Source\Executables\MyApp
Context: I'm in charge of running a service written in .NET. Proprietary application. It
Context: So, I am attempting to build a ridiculously complex domain model. Talking with
Context : programming a c/c++ win32-mfc library How to know whether we are in
Context PHP 5.3.x Overview After doing a code-review with an associate who uses both
For context, I am something of an emacs newbie. I haven't used it for
Some context upfront: Imagine a 200+ developers company finally setting up a more or
in context of SQL Server 2005, I have a table for which the primary
Some Context From Javascript: The Definitive Guide : When regexp is a global regular
Some context: one of the systems I'm working on is a .net 2.0 web

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.