Below is code that I want to be able to use simple
LoadLibrary\GetProcAddress\FreeLibrary technqiues on. I've used the code that
was initially placed on the .NET 247 forum as such:
http://dotnet247.com/247reference//msgs/28/140461.aspx
I have expanded it here to let one call any/all kinds of functions. The idea
is that a "MASTER" Invoke function takes arrays that explain everything
needed to be able to call functionality as one desires, while overloaded
version of "Invoke" that are prepped for the means\design we wish to cal them
as build the arrays as need be. If anyone would please, help me fill in the
blanks as denoted by the various "????" spots.
====================
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
namespace MyNameSpace
{
public class MyClass
{
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string csFileName);
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr IntPtr_Module, string
csProcName);
[DllImport("kernel32.dll")]
static extern bool FreeLibrary(IntPtr IntPtr_Module);
public main()
{
IntPtr IntPtr_MyLib = LoadLibrary("MyLib.dll");
IntPtr IntPtr_MyFunc = GetProcAddress(IntPtr_MyLib, "MyFunc");
string csRET = Invoke(IntPtr_MyFunc, "Param #1", "Param #2");
FreeLibrary(IntPtr_MyFunc);
}
public static string Invoke(IntPtr IntPtr_Function, string csParam1,
string csParam2)
{
object[] zobject_Parameters = new object[]
{
csParam1,
csParam2
};
Type[] zType_ParameterTypes = new Type[]
{
typeof(string),
typeof(string)
};
String[] zcsParameterTypes = new String[]
{
"string",
"string"
};
Type Type_Return = typeof(string);
return (string) Invoke
(
IntPtr_Function,
zobject_Parameters,
zType_ParameterTypes,
zcsParameterTypes,
Type_Return
);
}
public static object Invoke
(
IntPtr IntPtr_Function,
object[] zobject_Parameters,
Type[] zType_ParameterTypes,
String[] zcsParameterTypes,
Type Type_Return
)
{
AssemblyName AssemblyName_This = new AssemblyName();
AssemblyName_This.Name = "Invokable";
AssemblyBuilder AssemblyBuilder_This =
AppDomain.CurrentDomain.DefineDynamicAssembly
(
AssemblyName_This,
AssemblyBuilderAccess.Run
);
ModuleBuilder ModuleBuilder_This =
AssemblyBuilder_This.DefineDynamicModule
(
"CInvoker"
);
MethodBuilder MethodBuilder_This = ModuleBuilder_This.DefineGlobalMethod
(
"Invoker",
MethodAttributes.Public | MethodAttributes.Static,
Type_Return,
zType_ParameterTypes
);
ILGenerator ILGenerator_This = MethodBuilder_This.GetILGenerator();
int i;
OpCode OpCode_Integer;
if (IntPtr.Size == 4)
{
OpCode_Integer = OpCodes.Ldc_I4;
}
else if (IntPtr.Size == 8)
{
OpCode_Integer = OpCodes.Ldc_I8;
}
else
{
throw new PlatformNotSupportedException();
}
for (i = 0; i < zobject_Parameters.Length; i++)
{
switch (zcsParameterTypes[i])
{
case "sbyte":
ILGenerator_This.Emit(????, (sbyte) zobject_Parameters[i]);
break;
case "byte":
ILGenerator_This.Emit(????, (byte) zobject_Parameters[i]);
break;
case "char":
ILGenerator_This.Emit(????, (char) zobject_Parameters[i]);
break;
case "short":
ILGenerator_This.Emit(????, (short) zobject_Parameters[i]);
break;
case "ushort":
ILGenerator_This.Emit(????, (ushort) zobject_Parameters[i]);
break;
case "int":
ILGenerator_This.Emit(OpCode_Integer, (int)
zobject_Parameters[i]);
break;
case "uint":
ILGenerator_This.Emit(OpCode_Integer, (uint)
zobject_Parameters[i]);
break;
case "long":
ILGenerator_This.Emit(OpCodes.Ldc_I8, (long)
zobject_Parameters[i]);
break;
case "ulong":
ILGenerator_This.Emit(OpCodes.Ldc_I8, (ulong)
zobject_Parameters[i]);
break;
case "float":
ILGenerator_This.Emit(OpCodes.Ldc_R4, (float)
zobject_Parameters[i]);
break;
case "double":
ILGenerator_This.Emit(OpCodes.Ldc_R8, (double)
zobject_Parameters[i]);
break;
case "string":
ILGenerator_This.Emit(????OpCodes.Ldstr, (string)
zobject_Parameters[i]);
break;
case "StringBuilder":
ILGenerator_This.Emit(????OpCodes.Ldstr, (StringBuilder)
zobject_Parameters[i]);
break;
default:
throw
(
new Exception
(
"The parameter #" + i.ToString() + " is not a valid type for
invocation"
)
);
break;
}
}
ILGenerator_This.EmitCalli
(
OpCodes.Calli,
CallingConvention.StdCall,
Type_Return,
zType_Parameters
);
ILGenerator_This.Emit(OpCodes.Ret);
ModuleBuilder_This.CreateGlobalFunctions();
MethodInfo MethodInfo_This = ModuleBuilder_This.GetMethod("Invoker");
return MethodInfo_This.Invoke(null, zobject_Parameters);
}
}
}
public static object Invoke
(
IntPtr IntPtr_Function,
object[] zobject_Parameters,
Type[] zType_ParameterTypes,
String[] zcsParameterTypes,
Type Type_Return
)
{
// To begin, we will setup a temporary assembly, module, and method
which we will use JIT
// technqiues to build, that will call our desired function.
AssemblyName AssemblyName_This = new AssemblyName();
AssemblyName_This.Name = "Invokable";
AssemblyBuilder AssemblyBuilder_This =
AppDomain.CurrentDomain.DefineDynamicAssembly
(
AssemblyName_This,
AssemblyBuilderAccess.Run
);
ModuleBuilder ModuleBuilder_This =
AssemblyBuilder_This.DefineDynamicModule
(
"CInvoker"
);
MethodBuilder MethodBuilder_This = ModuleBuilder_This.DefineGlobalMethod
(
"Invoker",
MethodAttributes.Public | MethodAttributes.Static,
Type_Return,
zType_ParameterTypes
);
ILGenerator ILGenerator_This = MethodBuilder_This.GetILGenerator();
int i;
OpCode OpCode_Integer;
// We must now push each paramter onto the stack.
// We must now push the function pointer onto the stack.
if (IntPtr.Size == 4)
{
ILGenerator_This.Emit(OpCode_Integer, IntPtr_Function.ToInt32());
}
else if (IntPtr.Size == 8)
{
ILGenerator_This.Emit(OpCode_Integer, IntPtr_Function.ToInt64());
}
else
{
throw new PlatformNotSupportedException();
}
// Now we pop the parameters, and the function from the stack, which
makes the call to the
// function. After which, we push the return type onto the stack.
ILGenerator_This.EmitCalli
(
OpCodes.Calli,
CallingConvention.StdCall,
Type_Return,
zType_Parameters
);
ILGenerator_This.Emit(OpCodes.Ret);
// At this point, out code for the JIT is ready. We now need to
actually call it, and
// return its results.
--
- Nicholas Paldino [.NET/C# MVP]
- m...@spam.guard.caspershouse.com
"ATS" <A...@discussions.microsoft.com> wrote in message
news:3881C86A-1F5B-4FFC...@microsoft.com...
Now, for clarification, I do not need the prototype of the function to be
dynamic, I can live with using (for the moment) a hard coded prototype, so
long as the DLL is not statically coded.
By the way, I've changed the Invoke function from other posts on google as
such:
=======================
public static string Invoke(IntPtr IntPtr_Function, string csParam1,
string csParam2)
{
object[] zobject_Parameters = new object[]
{
csParam1,
csParam2
};
Type[] zType_ParameterTypes = new Type[]
{
typeof(string),
typeof(string)
};
String[] zcsParameterTypes = new String[]
{
"value",
"value"
};
Type Type_Return = typeof(string);
return (string) Invoke
(
IntPtr_Function,
zobject_Parameters,
zType_ParameterTypes,
zcsParameterTypes,
Type_Return
);
}
public static object Invoke
(
IntPtr IntPtr_Function,
object[] zobject_Parameters,
Type[] zType_ParameterTypes,
String[] zcsParameterTypes,
Type Type_Return
)
{
// To begin, we will setup a temporary assembly, module, and method
which we will use JIT
// technqiues to build, that will call our desired function.
AssemblyName AssemblyName_This = new AssemblyName();
AssemblyName_This.Name = "Invokable";
AssemblyBuilder AssemblyBuilder_This =
AppDomain.CurrentDomain.DefineDynamicAssembly
(
AssemblyName_This,
AssemblyBuilderAccess.Run
);
ModuleBuilder ModuleBuilder_This =
AssemblyBuilder_This.DefineDynamicModule
(
"CInvoker"
);
MethodBuilder MethodBuilder_This = ModuleBuilder_This.DefineGlobalMethod
(
"Invoker",
MethodAttributes.Public | MethodAttributes.Static,
Type_Return,
zType_ParameterTypes
);
ILGenerator ILGenerator_This = MethodBuilder_This.GetILGenerator();
int i;
// We must now push each paramter onto the stack. As we do, we must
push them on to reflect
// whether they are static values, or references.
for (i = 1; i <= zobject_Parameters.Length; i++)
{
switch (zcsParameterTypes[i - 1])
{
case "value":
ILGenerator_This.Emit(OpCodes.Ldarg, i);
break;
case "address":
ILGenerator_This.Emit(OpCodes.Ldarga, i);
break;
default:
throw
(
new Exception
(
"The parameter #" + i.ToString() + " does not have a valid
reference type"
)
);
}
}
// We must now push the function pointer onto the stack.
if (IntPtr.Size == 4)
{
ILGenerator_This.Emit(OpCodes.Ldc_I4, IntPtr_Function.ToInt32());
}
else if (IntPtr.Size == 8)
{
ILGenerator_This.Emit(OpCodes.Ldc_I8, IntPtr_Function.ToInt64());
}
else
{
throw new PlatformNotSupportedException();
}
// Now we pop the parameters, and the function from the stack, which
makes the call to the
// function. After which, we push the return type onto the stack.
ILGenerator_This.EmitCalli
(
OpCodes.Calli,
CallingConvention.StdCall,
Type_Return,
zType_ParameterTypes
);
ILGenerator_This.Emit(OpCodes.Ret);
// At this point, out code for the JIT is ready. We now need to
actually call it, and
// return its results.
ModuleBuilder_This.CreateGlobalFunctions();