|
-
Oct 28th, 2007, 11:39 AM
#1
Thread Starter
Member
[RESOLVED] loading C dlls in C#
hello,
i'm working on a way to load a dll i made in C into C#. I made a simple function that returns a string "hello" and C# calls this function and gets the string just fine. I then tried to pass a structure to C#, but this causes errors.
my C code structure
Code:
typedef struct _MY_STRUCT
{
int sName;
int sPhone;
}MY_STRUCT, *LPMY_STRUCT;
my C# structure
Code:
public struct MY_STRUCT
{
public int sName;
public int sPhone;
}
whenever I call
Code:
MY_STRUCT MyStruct = new MY_STRUCT();
//MessageBox.Show(Marshal.SizeOf(MyStruct).ToString());
//compiler doesnt like this line...
Marshal.PtrToStructure(GetString(), MyStruct);
MessageBox.Show(MyStruct.sName.ToString());
MessageBox.Show(MyStruct.sPhone.ToString());
I get a runtime error: "The structure must not be a value class.
Parameter name: structure"
I've also just tried doing this:
Code:
MyStruct = GetString(); //GetString is just the name of the function
but all i get is a runtime error saying type signiture is not compatible
by using sizeof, I know that both the C structure and the C# structure are 8 bytes long, but I dont know what else to do (and ive tried everything I could think of)
Please, could someone help me?
-
Oct 28th, 2007, 06:27 PM
#2
Re: loading C dlls in C#
I'm not sure why a method named "GetString" would return a structure with two int fields but, that aside, can we see the C definition of the function and also the C# declaration?
-
Oct 29th, 2007, 12:10 AM
#3
Thread Starter
Member
Re: loading C dlls in C#
ok, i tried it with integers and still no luck, here is the code:
Code:
typedef struct _MY_STRUCT
{
int iName;
int iPhone;
}MY_STRUCT, *LPMY_STRUCT;
C_EXPORT LPMY_STRUCT __cdecl GetInterface (void)
{
static struct _MY_STRUCT XMPTagInterface;
memset(&XMPTagInterface,0,sizeof(XMPTagInterface));
XMPTagInterface.iName=1234;
XMPTagInterface.iPhone=5678;
return &XMPTagInterface;
}
thats how it is in the dll
in C#
Code:
public struct MY_STRUCT
{
public int iName;
public int iPhone:
}
[DllImport("tag_interface.dll")]
public static extern IntPtr GetInterface();
|--------------------i dunno if this is the right type
I also tried MY_STRUCT
//in some private meothod
MY_STRUCT MyStruct = new MY_STRUCT();
//compiler hates this line-----------------|
Marshal.PtrToStructure(GetInterface(), MyStruct);
says it cant be a value type structure I don;t event know what that means...lol
this code works fine when i load my test dll in my C app, but C# chokes on it
I dunno what to do. and sorry for the sadly written example
-
Oct 29th, 2007, 12:35 AM
#4
Re: loading C dlls in C#
There are two overloads of PtrToStructure. The one you are using cannot be used with value types, as the error message says. That means that the second parameter must be an instance of a class or other reference type, NOT a structure. If you want to marshal to a value type then you must use the other overload. In that case you specify the type and the method returns a boxed instance, which you must unbox by casting:
CSharp Code:
MyStruct s = (MyStruct)Marshal.PtrToStructure(GetInterface(), typeof(MyStruct));
-
Oct 29th, 2007, 01:47 AM
#5
Thread Starter
Member
Re: loading C dlls in C#
oh... 
thanks!
-
Oct 29th, 2007, 07:42 AM
#6
Re: [RESOLVED] loading C dlls in C#
This would be easier to do with unsafe code but since you've got a working solution I won't bother going into detail unless you want me to.
I don't live here any more.
-
Oct 29th, 2007, 09:21 AM
#7
Thread Starter
Member
Re: [RESOLVED] loading C dlls in C#
yeah, i was trying to do it without unsafe code. but the whole reason i'm doing this in the first place, is becuase writing a plugin system in C# is a nightmare. So, i'm doing my plugins in C and my main app in C# (at least until I master C# dlls )
-
Oct 29th, 2007, 05:28 PM
#8
Re: [RESOLVED] loading C dlls in C#
 Originally Posted by nci
writing a plugin system in C# is a nightmare.
Since when? I've never done it myself but I've read about it and it seems pretty simple to me. What exactly is so nightmarish about it?
-
Oct 29th, 2007, 06:19 PM
#9
Thread Starter
Member
Re: [RESOLVED] loading C dlls in C#
well, i viewed a few exaples and tutorials for it, but I'm soo lost. I just dont know enough about inheritence and interfaces yet. It just looks sooo complicated. eventually i'll understand it, but right now, its easier for me to manage plugins in C code
-
Oct 29th, 2007, 07:06 PM
#10
Re: [RESOLVED] loading C dlls in C#
It's actually not very complicated at all, but if you want to stick to C plugins for the moment then fair enough.
As for interfaces, they're pretty much like a C header file, with a list of methods but no implementation for any of them. Classes can then implement that interface by providing an implementation for each of the members it defines. You can then have various disparate types all able to be acst as the same type and therefore used in the same way.
For a real-life example, consider your computer and how many varied peripherals are attached to it, or could be attached to it. It's likely that many of those peripherals would have a USB interface. It doesn't matter what the peripherals do or how they do it, as long as they implement the USB interface your computer can talk to them.
Your app would be the same. You define the interface a plugin must implement. You can then load any and all plugins no matter what they do or how they do it. All your app cares about is that they implement your interface. The interface is just a bunch or method and property signatures. How each method and property is implemented is completely up to the discretion of the plugin author.
-
Oct 29th, 2007, 07:27 PM
#11
Re: [RESOLVED] loading C dlls in C#
Here's a quick code example:
csharp Code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Plugin1 p1 = new Plugin1();
Plugin2 p2 = new Plugin2();
this.AboutPlugin(p1);
this.AboutPlugin(p2);
}
private void AboutPlugin(IPlugin plugin)
{
plugin.About();
}
}
public interface IPlugin
{
void About();
}
public class Plugin1 : IPlugin
{
#region IPlugin Members
void IPlugin.About()
{
MessageBox.Show("All about Plugin1");
}
#endregion
}
public class Plugin2 : IPlugin
{
#region IPlugin Members
void IPlugin.About()
{
MessageBox.Show("All about Plugin2");
}
#endregion
}
Note that the IPlugin interface declares a method named About that takes no parameters and returns no value. It provides no implementation, leaving that up to the classes that will implement the interface. The Plugin1 and Plugin2 classes both implement the IPlugin interface, and therefore implement the IPlugin.About method. Each class implements the method as it sees fit.
Withing the application the objects are treated as IPlugin objects, not there actual type. Because the IPlugin type has an About method we know we can call that method on any and all plugins.
In a real situation each of the plugin classes would be declared in its own DLL and you would load those DLLs at run time and access the class using reflection. That adds some complexity but it's still just a few lines of code to do that.
-
Oct 30th, 2007, 03:59 AM
#12
Re: [RESOLVED] loading C dlls in C#
You could also abstract it a little and create a new instance by doing it like so...
Code:
IPlugin plgIn = new Plugin1();
-
Oct 30th, 2007, 04:20 AM
#13
Re: [RESOLVED] loading C dlls in C#
 Originally Posted by Hell-Lord
You could also abstract it a little and create a new instance by doing it like so...
Code:
IPlugin plgIn = new Plugin1();
In a real situation you couldn't because you won't have compile-time references to the DLLs containing the plugins, so you won't know the Plugin1 type. You have to load the DLLs at run time and interrogate them using reflection.
-
Oct 30th, 2007, 04:29 AM
#14
Re: [RESOLVED] loading C dlls in C#
Inside the DLL can't you do...
Code:
[assmebly: Plugin(typeof(myplugin))]
-
Oct 30th, 2007, 09:30 AM
#15
Thread Starter
Member
Re: [RESOLVED] loading C dlls in C#
that was the first real example that made sense. See, normally for my C programs, i create a type structure that has all of the plugin details, like name, author, description, and a bunch of function pointers that are required (pretty much the interface) then I just pass the structure off to the app, and the app would call the plugin functions like
Code:
MyPlugin[2]->DoMath(2, 4); //what it does with 2 and 4 is up to the plugin
i like your example, jmcilhinney, it makes it look really simple. I've looked at all kinds of tutorials and my head was spinning. So, i may give this a shot.
All of the examples i've seen had an interface dll and also plugin dlls. Is this the way it has to be? or can an app just look at a directory and load all of the dlls in it?
currently, my C# app uses a dll that controls the other plugins, simply becuase I do not quiet no how to load dlls at runtime. I suppose i could import a LoadLibrary api, but, I didnt think of that till just now 
anyway, i'm still learning C# and it is quickly becoming my favorite language.
-
Oct 30th, 2007, 06:31 PM
#16
Re: [RESOLVED] loading C dlls in C#
The general idea would be that you would have a folder dedicated to plugins, into which each author would install their DLL. An alternative could be that you have a registry key dedicated to storing the locations of plugin libraries, where each athor would add the path to their library and you'd read it from there.
You should take a look at the Assembly class, which is used to load assemblies at run time. I've never actually done this stuff myself so I don't know all the details, but basically you load the assembly and then interrogate it to find types that implement your plugin interface. The interrogation is done using reflection, which you can read about in the documentation for the System.Reflection namespace and the System.Type class.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|