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;
}