RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Dynamically load an unmanaged dll from C#

Smjert

Sorceror
Dynamically load an unmanaged dll from C#

I need to load dynamically an unmanaged dll with C#, so something like a program that accepts plugins.
This dll also have an abstract class that should be something like an interface, and his functions has to be called by C# part.
I know that in C# with managed dll you load it with Assembly.LoadFrom(), then you search with LINQ if there's that type of interface you're searching for, then if you find it you "select" it, and with Assembly.CreateInstance you create an object that is linked to the dll interface.
So how to do the same thing with an unmanaged dll?
Thnks.
 

Smjert

Sorceror
Ok i find myself, it should be rather simple to do.. the solution is to mix managed and unmanaged C++ and then use the managed C++ part to interface with C#.
 

Jeff

Lord
Smjert;802478 said:
I'll try, since i found that is not so simple to do with the mix of managed and unmanaged.

You just use P/Invoke... its not hard

Look up DLLImport.
 

Smjert

Sorceror
Jeff;802483 said:
You just use P/Invoke... its not hard

Look up DLLImport.

eh what i need is something like late binding, link to a dll at runtime..
With C# to C# dll the thing is very good since i can have an interface object to use to call the functions, with native c++ dll i have to use LoadLibrary, GetProcAddress to find the address of each function i want to call.. the problem is that it fails to find the function (it returns always 0).
So here i think there's a problem with C++, i don't know how to expose the function in my class.

Anyway here's what i have with C# code:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace SoftwareUpdater
{
	public partial class Form1 : Form
	{
		[DllImport("kernel32.dll")]
		internal static extern IntPtr LoadLibrary(String dllname);

		[DllImport("kernel32.dll")]
		internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);

		internal delegate string Test();
		public Form1()
		{
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			IntPtr ptrDll = LoadLibrary(@"path to dll");
			IntPtr procaddr = GetProcAddress(ptrDll, "Test");
			Test tst = (Test)Marshal.GetDelegateForFunctionPointer(procaddr, typeof(Test));
			textBox1.Text = tst();
		} 
	}
}

And here is the C++ part (SUInterface is not really needed anyway), header:

Code:
#include <string>

using namespace std;

class SUInterface
{
	public:
		virtual string Test() = 0;
};

class MyClass : public SUInterface
{
	public:
		MyClass();
		string Test();
};

module:
Code:
#include "SUInterface.h"

using namespace std;

string MyClass::Test()
{
	return "i work";
}
 

arul

Sorceror
Code smell, could you explain what are you trying to achieve?

1/ You're attempting to obtain an address of a member function.
2/ You certainly didn't export the function from the dll.

DllImport is more of a C-ish way of interoperability, if you really need to (though I doubt so) work on an object level you'll need COM.
 

Smjert

Sorceror
arul;802516 said:
Code smell, could you explain what are you trying to achieve?

1/ You're attempting to obtain an address of a member function.
2/ You certainly didn't export the function from the dll.

DllImport is more of a C-ish way of interoperability, if you really need to (though I doubt so) work on an object level you'll need COM.

I wrote it in the first post:

I need to load dynamically an unmanaged dll with C#, so something like a program that accepts plugins.

So plugins are loaded at runtime, i cannot use DllImport, i know how to do it with C# to C# and in this way i also have an interface to call all the functions.
I don't know if i can do the same thing with C++, i think not.. i have to declare all the delegates for each function i want to call i think.. but how to export C-ish member function? (and how to export a C++-ish member function?).
 

arul

Sorceror
That really sounds like you want to use COM.

Besides, you can use DllImport, you can generate a wrapper class at runtime using reflection.

C doesn't have member functions since there's no OOP support in it. For more information about exporting functions click here.
 

Smjert

Sorceror
I found this page and suddenly an idea popped into my mind.
I prepared a C# dll with the interface, that dll is loaded by the semi-managed C++ project, the managed class (who's a wrapper for unmanaged C++) inherits from the C# interface.
So in the other C# project i can use LINQ method to find the interface in the semi-managed C++ dll and use the functions.
So it works!
 

arul

Sorceror
I still don't get why do you need to mix C# with a managed C++, the second most fcked up language right after Objective C.
What does "LINQ method to find the interface [...] and use the functions" mean? Feels like you're reinventing the IDispatch interface.

Your whole point of plugins is somehow twisted, in most projects developers tend to use some sort of scripting language for plugins/addins, because it makes developing easier and faster. You're going the other way here, from nice and mostly safe C# into the valley of managed C++'s crazy syntax, which only a few really mastered.
 

Smjert

Sorceror
arul;802555 said:
I still don't get why do you need to mix C# with a managed C++, the second most fcked up language right after Objective C.
What does "LINQ method to find the interface [...] and use the functions" mean? Feels like you're reinventing the IDispatch interface.

Your whole point of plugins is somehow twisted, in most projects developers tend to use some sort of scripting language for plugins/addins, because it makes developing easier and faster. You're going the other way here, from nice and mostly safe C# into the valley of managed C++'s crazy syntax, which only a few really mastered.

Please define SAFE for C# :D
My problem is that C# can be simply decompilable, so this is why the plugin need to be native C++.
Also i took the idea to use a wrapper from here, because i need it to load the dll in an easy way.

Anyway this is the LINQ way (is not my code but it's similar):

Code:
private bool LoadExternalModule(string path)
    {
      bool foundSnapIn = false;
      Assembly theSnapInAsm = null;
      try
      {
        // Dynamically load the selected assembly.
        theSnapInAsm = Assembly.LoadFrom(path);
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message);
        return foundSnapIn;
      }
      // Get all IAppFunctionality compatible classes in assembly.
      var theClassTypes = from t in theSnapInAsm.GetTypes()
                          where t.IsClass &&
                          (t.GetInterface("ILanguage") != null)
                          select t;
      // Now, create the object and call DoIt() method.
      foreach (Type t in theClassTypes)
      {
        foundSnapIn = true;
        // Use late binding to create the type.
				ILanguage itfApp =
				( ILanguage )theSnapInAsm.CreateInstance( t.FullName, true );
				itfApp.WriteMyName();
      }

      return foundSnapIn;
    }
 

arul

Sorceror
See a thread here.

It's managed C++ which is still decompilable, and I still somehow fail to see why you're exposing your main functionality in an managed app, and trying to protect "plugin" code.
 

Smjert

Sorceror
arul;802591 said:
See a thread here.

It's managed C++ which is still decompilable, and I still somehow fail to see why you're exposing your main functionality in an managed app, and trying to protect "plugin" code.

Wrong, the C# part of my program is only forms, so the graphics and the interfaces, the real implementation is in native C++, i need MC++ only in plugin, to load and unload at runtime.
 
Top