In c# can you dynamically load an unmanaged DLL and also dynamically specify the function call?

107 views Asked by At

I need to dynamically load an unmanaged DLL and dynamically specify the function calls and parameters. In examples I found you and methods I used in the past you statically specify the delegate in the top of the class. I am not sure this is even possible.

The following is and example of static delegate part, but also has the non working dynamically defined delegate also.

using System;
using System.Runtime.InteropServices;
using System.IO;

class Program
{
  //Declare the delegate to represent the function signature I want to do this dynamically
  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  private delegate int MyFunctionDelegate(int a, int b);

  static void Main()
  {
    try
    {
      //Change path to dll
      string dllPath = @"C:\Projects_VS\Tests\DynamicLoadDLLTest\simpleCDLL.dll";
      //function name to call
      string functionName = "Add";

      if (!File.Exists(dllPath))
      {
        Console.WriteLine("Missing DLL file.");
      }

      // Dynamically load the user-specified DLL
      IntPtr dllHandle = LoadLibrary(dllPath);

      if (dllHandle == IntPtr.Zero)
      {
        Console.WriteLine("Failed to load the DLL.");
        return;
      }


      // Get the function address from the loaded DLL
      IntPtr functionAddress = GetProcAddress(dllHandle, functionName);
      if (functionAddress == IntPtr.Zero)
      {
        Console.WriteLine("Failed to get the function address.");
        return;
      }

      // Currently works
      MyFunctionDelegate myFunction = Marshal.GetDelegateForFunctionPointer<MyFunctionDelegate>(functionAddress);
      int result = myFunction(10, 20);

      //What I want to do 
      IntPtr functionPtr = GetProcAddress(dllHandle, "Add");
      delegate int DynamicFunctionDelegate(int parameter1, int parameter2); 
      DynamicFunctionDelegate myFunction = Marshal.GetDelegateForFunctionPointer<DynamicFunctionDelegate>(functionPtr);
      int result = myFunction(10, 20);

      Console.WriteLine("Result: " + result);
    }
    catch (Exception ex)
    {
      Console.WriteLine("An error occurred: " + ex.Message);
    }
  }

  // Helper method to dynamically load the DLL
  [DllImport("kernel32.dll")]
  private static extern IntPtr LoadLibrary(string dllToLoad);

  // Helper method to get the function address from the loaded DLL
  [DllImport("kernel32.dll")]
  private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
}

Update - I found a different example (http://netcode.ru/dotnet/?lang=&katID=30&skatID=264&artID=7243) and modified it but it isn't calling the DLL. Is this a valid path to follow?

static void Main()
{
  //Change path to dll
  string dllPath = @"E:\Projects_VS\Tests\DynamicLoadDLLTest\SimpleCDLL.dll";
  //function name to call
  string functionName = "Add";
  object[] parameterValues = { 5, 10 };

  object r = DynamicDllFunctionInvoke(dllPath, functionName, parameterValues);

}


public static object DynamicDllFunctionInvoke(string DllPath, string entrypoint, object[] funcPrams)
{
  //Define return type of your dll function.
  Type returnType = typeof(int);
  //out or in parameters of your function.
  int n = funcPrams.Length;
  Type[] parameterTypes = new Type[n];
  for (int i =0; i<n; ++i)
  {
    parameterTypes[i] = funcPrams[i].GetType();
  }
  string entryPoint = entrypoint;

  // Create a dynamic assembly and a dynamic module
  AssemblyName asmName = new AssemblyName();
  asmName.Name = "tempDll";
  AssemblyBuilder dynamicAsm = AssemblyBuilder.DefineDynamicAssembly(asmName,
          AssemblyBuilderAccess.Run);
  ModuleBuilder dynamicMod =
    dynamicAsm.DefineDynamicModule("tempModule");

  // Dynamically construct a global PInvoke signature 
  // using the input information
  MethodBuilder dynamicMethod = dynamicMod.DefinePInvokeMethod(
    entryPoint, DllPath, MethodAttributes.Static | MethodAttributes.Public
    | MethodAttributes.PinvokeImpl, CallingConventions.Standard,
    returnType, parameterTypes, CallingConvention.Winapi,
    CharSet.Ansi);

  // This global method is now complete
  dynamicMod.CreateGlobalFunctions();

  // Get a MethodInfo for the PInvoke method
  MethodInfo mi = dynamicMod.GetMethod(entrypoint);
  // Invoke the static method and return whatever it returns
  object retval = mi.Invoke(null, funcPrams);

  return retval;
}
0

There are 0 answers