By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,962 Members | 1,415 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,962 IT Pros & Developers. It's quick & easy.

HOWTO Implement LoadLibrary, GetProcAdress, and FreeLibrary.

P: n/a
ATS
HOWTO Implement LoadLibrary, GetProcAdress, and FreeLibrary.

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

Nov 17 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
ATS
I forgot to add some code to the "Invoke" function as such:
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.

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

// 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.

ModuleBuilder_This.CreateGlobalFunctions();
MethodInfo MethodInfo_This = ModuleBuilder_This.GetMethod("Invoker");
return MethodInfo_This.Invoke(null, zobject_Parameters);
}

Nov 17 '05 #2

P: n/a
This is completely the wrong way to go about this. I've already pointed
you in the direction to go if you are using .NET 2.0. If you are using .NET
1.1 and before, then you will want to create a shim in unmanaged code which
will make the call to LoadLibrary/GetProcAddress, and return a delegate to
you.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"ATS" <AT*@discussions.microsoft.com> wrote in message
news:38**********************************@microsof t.com...
HOWTO Implement LoadLibrary, GetProcAdress, and FreeLibrary.

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

Nov 17 '05 #3

P: n/a
ATS
Thanks for the reply, but without having it completely spoon fed I have no
wheres to go but this approach. I need the full
LoadLibray\GetProcAddress\FreeLibrary, in C#. I can not use static mechanisms
to load my DLL, as the DLL will not exists until run time. And the function
prototype will not necessarily be static either. This approach was taken on
by others to basically use the JIT to FORCE C# into working with
LoadLibrary\GetProcAddress\FreeLibrary exactly as I need it, where both the
DLL is not know until run time, and the prototype of the function to call is
also not known until run time.

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();
MethodInfo MethodInfo_This = ModuleBuilder_This.GetMethod("Invoker");
return MethodInfo_This.Invoke(null, zobject_Parameters);
}

Nov 17 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.