Use Gsof.Native to dynamically call the C dynamic library
Background
When using C ා to develop clients, we often call some standard dynamic libraries or C class libraries.
Although the PInvoke method provided by C ා, due to the variety of scenarios used, sometimes it may not be possible to call at a fixed location, or to call different libraries as required.
Two, explain
- Support dynamic loading of DLL class library according to path
- Support using to destroy the loaded class library
- Easy to call
github: https://github.com/gaoshang212/gsof/tree/master/Gsof.Native
nuget: https://www.nuget.org/packages/Gsof.Native/
Interface Description:
NativeFactory creates an intrinsic calling object:
/// <summary>
/// Establish INative object
/// </summary>
/// <param name="p_fileName">File path</param>
/// <returns></returns>
public static INative Create(string p_fileName);
/// <summary>
/// Establish INative object
/// </summary>
/// <param name="p_fileName">File path</param>
/// <param name="p_calling">Call conversion method (same as PInvoke CallingConvention)/param>
/// <returns></returns>
public static INative Create(string p_fileName, CallingConvention _calling);
/// <summary>
/// Destruction INative, You can also call Native Of Dispose Method
/// </summary>
/// <param name="p_native"></param>
public static void Free(INative p_native);
INative:
public interface INative : IDisposable
{
/// <summary>
/// Get function delegate
/// </summary>
/// <typeparam name="TDelegate"></typeparam>
/// <returns></returns>
TDelegate GetFunction<TDelegate>();
/// <summary>
/// Function delegate call method
/// </summary>
/// <typeparam name="TResult">return type</typeparam>
/// <typeparam name="TDelegate">Delegate type corresponding to function</typeparam>
/// <param name="p_params">Function reference</param>
/// <returns></returns>
TResult Invoke<TResult, TDelegate>(params object[] p_params);
/// <summary>
/// Function name call
/// </summary>
/// <typeparam name="TResult">return type</typeparam>
/// <param name="p_funName">Function name</param>
/// <param name="p_params">Function reference</param>
/// <returns></returns>
TResult Invoke<TResult>(string p_funName, params object[] p_params);
/// <summary>
/// Function name call
/// </summary>
/// <typeparam name="TResult">return type</typeparam>
/// <param name="p_funName">Function name</param>
/// <param name="p_calling">Call conversion method (same as PInvoke CallingConvention)</param>
/// <param name="p_params">Function reference</param>
/// <returns></returns>
TResult Invoke<TResult>(string p_funName, CallingConvention p_calling, params object[] p_params);
/// <summary>
/// Function name call(Non generic)
/// </summary>
/// <param name="p_funName">Function name</param>
/// <param name="p_retrunType">return type</param>
/// <param name="p_params">Function reference</param>
/// <returns></returns>
object Invoke(string p_funName, Type p_retrunType, params object[] p_params);
/// <summary>
/// Function delegate call method
/// </summary>
/// <typeparam name="TDelegate">Delegate type corresponding to function</typeparam>
/// <param name="p_params">Function reference</param>
void Call<TDelegate>(params object[] p_params);
/// <summary>
/// Function name call
/// </summary>
/// <param name="p_funName">Function name</param>
/// <param name="p_params">Function reference</param>
void Call(string p_funName, params object[] p_params);
/// <summary>
/// Function name call
/// </summary>
/// <param name="p_funName">Function name</param>
/// <param name="p_calling">Call conversion method (same as PInvoke CallingConvention)</param>
/// <param name="p_params">Function reference</param>
void Call(string p_funName, CallingConvention p_calling, params object[] p_params);
}
Three, use
libtest.dll includes a test function for
int test(int input)
{
return input;
}
Method name call
int input = 0;
int result = -1;
using (var native = NativeFactory.Create(@"../../libtest.dll"))
{
result = native.Invoke<int>("test", input);
}
dynamic mode call
- Advantages: easy to call, simple type calls, do not do too much definition.
- Disadvantages: the performance under 4.0 is not ideal, and 4.5 + performance is much better, but it is worse than the way of delegation.
int input = 0;
int result = -1;
using (dynamic native = NativeFactory.Create(@"../../libtest.dll"))
{
result = native.test<int>(input);
}
Delegate method call
- Optimization: high efficiency, without the consumption of the first dynamic construction of delegation, function delegation can be obtained to increase the consumption of repeated calls
- Disadvantages: if there are many functions, the definition of delegation is cumbersome
[NativeFuncton("test")]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int Test(int p_sleep);
public void DelegateFunction()
{
int input = 0;
int result = -1;
using (var native = NativeFactory.Create(@"../../libtest.dll"))
{
// Direct call
var result1 = native1.Invoke<int, Test>(input);
// Get function delegate call
var test = native.GetFunction<Test>();
result = test(input);
}
Assert.AreEqual(input, result);
}