1

Ex: in app1 user creates function_1() and function_2(). Then in app2 user wants to call function_2(). I searched on google and the only thing I found was to write this code:

    class Program
{
    [DllImport("functions.dll")]
    public static extern void function_1();


    static void Main(string[] args)
    {
        function_1();
    }
}
ale93
  • 11
  • 4
  • So the obvious inference here is that this is an unmanaged (non .NET DLL?) – David W Jun 04 '15 at 13:07
  • The only way you can selectively load a DLL at runtime is with LoadLibrary, although I'm not strictly sure this matches up with your requirements. There's an excellent if a bit dated article at http://goo.gl/hm4NVz (had to post shortened link) that covers this in detail. – David W Jun 04 '15 at 13:17

3 Answers3

3

You'll have to use some PInvoke code to get the DLL loaded (LoadLibrary) and to get a function pointer (GetProcAddess) and Marshal.GetDelegateForFunctionPointer to obtain a delegate that you can then invoke.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
0

Full example of what Damien wrote... Note that it works only if methods have all the same signature (in this example void function_X()). Additionally it is "difficult" to explore a dll to discover what methods are exported, so it is better if you already know what methods there should be in the dll.

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

// Set the correct calling convention
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DllMethodDelegate();

IntPtr dll = LoadLibrary(@"PathToYourDll.DLL");

if (dll == IntPtr.Zero)
{
    throw new Exception();
}

string methodName = "function_1";

IntPtr method = GetProcAddress(dll, methodName);

if (method == IntPtr.Zero)
{
    throw new Exception();
}

DllMethodDelegate method2 = (DllMethodDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(DllMethodDelegate));

// Now you can do method2();

Note that you have to set the correct calling convention in the DllMethodDelegate() definition. Normally dll methods should be StdCall.

The signature for the method you wrote is:

[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private delegate int DllMethodDelegate(char cmd, ref IntPtr out_address);

Note that "filling" the out_address is very complex (headache complex).

{
    // I case:
    IntPtr ret = IntPtr.Zero;
    int result = method2('I', ref ret);
}

{
    // R case:
    IntPtr ptr = IntPtr.Zero;

    int result = method2('R', ref ptr);

    int value = Marshal.ReadInt32(ptr);
}

{
    // W case:
    int value = 100;

    GCHandle handle = default(GCHandle);

    try
    {
        int[] value2 = new int[] { value };

        handle = GCHandle.Alloc(value2, GCHandleType.Pinned);
        IntPtr ptr = handle.AddrOfPinnedObject();

        int result = method2('W', ref ptr);
    }
    finally
    {
        if (handle.IsAllocated)
        {
            handle.Free();
        }
    }
}

It is possible (but I'm not sure) that for the third example, you could do

object value2 = value;

instead of

int[] value2 = new int[] { value };

The interaction of boxing and GCHandle isn't very documented, but it seems to work. C# specifications 4.3 seems to ok it... but I wouldn't trust it, and this technique seems to be described in the book ".NET and COM: The Complete Interoperability Guide", in the chapter "Obtaining the Address of Value Types" (that chapter is searchable in google, use the exact chapter title I gave. The example is in VB.NET but it is quite clear to read)

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • @ale93 It was mangled totally by the SO... Try pasting it in the question. – xanatos Jun 04 '15 at 14:06
  • @ale93 If you have multiple signature types (in this case multiple return types == multiple signatures), you'll have to handle them manually through multiple delegate types... And that `void**`, I don't think it can be easily done in C#. – xanatos Jun 04 '15 at 14:14
  • @ale93 Added an example of calling in the three modes. – xanatos Jun 04 '15 at 14:35
0

You can use SymEnumerateSymbols64 from dbghelp dll to obtain the list of existent functions in your DLL. Then the user can choose which function to run.

You can find a more detailed explanation here: C# get the list of unmanaged C dll exports

Community
  • 1
  • 1
Filip
  • 1
  • 1