yewnix
asked on
C# dll shared memory
I'm a little confused here.
What I have is a 3rd party application. This 3rd party application allows you to create scripts and import DLLs to call DLL Functions.
What I need to do is shared data between this 3rd party application and my c# application.
ie: 3rd party application runs script which calls my dll function add_data.. at this point my c# application reads the data from the memory map, delete it, does some calculations, and then writes back to the memory map that the 3rd party application would then read(using a dll call)
Any help would be greatly appreciated.
What I have is a 3rd party application. This 3rd party application allows you to create scripts and import DLLs to call DLL Functions.
What I need to do is shared data between this 3rd party application and my c# application.
ie: 3rd party application runs script which calls my dll function add_data.. at this point my c# application reads the data from the memory map, delete it, does some calculations, and then writes back to the memory map that the 3rd party application would then read(using a dll call)
Any help would be greatly appreciated.
I would suggest not using "unsafe" code as in my limited experience it ends up causing more headaches than it is worth.
I would look into the Marshaling class. You can allocated memory on the unmanaged heap and deallocated it later, you can pass a pointer to this memory and you can copy managed memory to and from this memory.
Here is a link:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.aspx
If you post more details (like the method signatures of the DLL you are calling) maybe you can even set it up to let the marshaller do automatic marshaling.
I would look into the Marshaling class. You can allocated memory on the unmanaged heap and deallocated it later, you can pass a pointer to this memory and you can copy managed memory to and from this memory.
Here is a link:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.aspx
If you post more details (like the method signatures of the DLL you are calling) maybe you can even set it up to let the marshaller do automatic marshaling.
unsafe is basically the same as working with native c++. if you use it with care, it will give you far more performance than the marshalling approach.
If you are a c++ developer, then use unsafe with confidence. If you are not familiarized with pointers, then use marshalling.
by the way, either using unsafe or marsalling, if your dll doesn't handle the buffer properly, you application will crash.
If you are a c++ developer, then use unsafe with confidence. If you are not familiarized with pointers, then use marshalling.
by the way, either using unsafe or marsalling, if your dll doesn't handle the buffer properly, you application will crash.
ASKER
Okay, maybe i'm not explaining this well enough so I'll give it a better shot.
Please forgive me as I am new to C#, however I do understand programming logic.. just never done Shared Memory or much with DLLs.
Okay I know the 3rd party application(MetaTrader 4) isn't developed in c#. So going from managed to unmanaged code might be difficult.
Say in my MetaTrader script I import my dll.
Call the Dll(inside the script) SendDllDate(string message);
After call this inside the script I'm going to want to call another Dll function that will basical Wait for a response(event driven inside the dll)
My C# application will read the MemoryMap, process the message sent by the 3rd party application. Then set an event and data inside the MemoryMap
The 3rd party application will jump back out of the Dll function(because an event was set) then and return the data that was placed into the MemoryMap from my c# application.
Based on the data retrieved it will process data inside the script.
Maybe I'm going about this the wrong way.. but I think I might be on the right track.
Please forgive me as I am new to C#, however I do understand programming logic.. just never done Shared Memory or much with DLLs.
Okay I know the 3rd party application(MetaTrader 4) isn't developed in c#. So going from managed to unmanaged code might be difficult.
Say in my MetaTrader script I import my dll.
Call the Dll(inside the script) SendDllDate(string message);
After call this inside the script I'm going to want to call another Dll function that will basical Wait for a response(event driven inside the dll)
My C# application will read the MemoryMap, process the message sent by the 3rd party application. Then set an event and data inside the MemoryMap
The 3rd party application will jump back out of the Dll function(because an event was set) then and return the data that was placed into the MemoryMap from my c# application.
Based on the data retrieved it will process data inside the script.
Maybe I'm going about this the wrong way.. but I think I might be on the right track.
ASKER
I basically want to build off of: (add a MemoryMap to store the data)
http://www.codeguru.com/csharp/csharp/cs_misc/dllsandexecutables/article.php/c14735/
In his c++ dll he does alot of converting.. is there a better way?
Also reference:
http://forum.mql4.com/6676/page2#30882
This shows the user using signed char* in the c++ dll.. However he doesn't pass back a string to the MetaTrader platform. He passes back a int. If this post is easier then converting(as in the first post) how can I change this to pass back the string to the MetaTrader platform?
http://www.codeguru.com/csharp/csharp/cs_misc/dllsandexecutables/article.php/c14735/
In his c++ dll he does alot of converting.. is there a better way?
Also reference:
http://forum.mql4.com/6676/page2#30882
This shows the user using signed char* in the c++ dll.. However he doesn't pass back a string to the MetaTrader platform. He passes back a int. If this post is easier then converting(as in the first post) how can I change this to pass back the string to the MetaTrader platform?
ASKER
Okay.. so here is what I have and it works so far. don't know if its the best method so advice would be helpful.
MetaTrader Script
----------------------
#import "mt4wrapper.dll"
string ReturnMyName(string fname, string lname);
int start()
{
Comment(ReturnMyName("Foo" , "Bar"));
return(0);
}
C++ Wrapper DLL (mt4wrapper.dll)
----------------------
#include "stdafx.h"
#using <mt4test.dll>
__declspec(dllexport) signed char* __stdcall ReturnMyName(signed char* fname, signed char* lname)
{
return mt4test::mt4test::ReturnMy Name(fname , lname);
}
C# DLL(mt4test.dll)
namespace mt4test
{
public unsafe static class mt4test
{
public static sbyte* ReturnMyName(sbyte* fname, sbyte* lname)
{
string name = "Your name is " + new string(fname) + " " + new string(lname);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding( );
byte[] r_name = enc.GetBytes(name);
return (sbyte*)VarPtr(r_name);
}
static int VarPtr(object o)
{
System.Runtime.InteropServ ices.GCHan dle GC =
System.Runtime.InteropServ ices.GCHan dle.Alloc( o,
System.Runtime.InteropServ ices.GCHan dleType.Pi nned);
int ret = GC.AddrOfPinnedObject().To Int32();
return ret;
}
}
}
This code actually works! When the MetaTrader script runs it does place in the comments section. "Your name is Foo Bar"
The only issue I see so far is I'm not unpinning the object after its being used.
Granted I still need to add all the MemoryMapping which ofcourse I'm new to that as well.
Any comments would be greatly appreciated!
MetaTrader Script
----------------------
#import "mt4wrapper.dll"
string ReturnMyName(string fname, string lname);
int start()
{
Comment(ReturnMyName("Foo"
return(0);
}
C++ Wrapper DLL (mt4wrapper.dll)
----------------------
#include "stdafx.h"
#using <mt4test.dll>
__declspec(dllexport) signed char* __stdcall ReturnMyName(signed char* fname, signed char* lname)
{
return mt4test::mt4test::ReturnMy
}
C# DLL(mt4test.dll)
namespace mt4test
{
public unsafe static class mt4test
{
public static sbyte* ReturnMyName(sbyte* fname, sbyte* lname)
{
string name = "Your name is " + new string(fname) + " " + new string(lname);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(
byte[] r_name = enc.GetBytes(name);
return (sbyte*)VarPtr(r_name);
}
static int VarPtr(object o)
{
System.Runtime.InteropServ
System.Runtime.InteropServ
System.Runtime.InteropServ
int ret = GC.AddrOfPinnedObject().To
return ret;
}
}
}
This code actually works! When the MetaTrader script runs it does place in the comments section. "Your name is Foo Bar"
The only issue I see so far is I'm not unpinning the object after its being used.
Granted I still need to add all the MemoryMapping which ofcourse I'm new to that as well.
Any comments would be greatly appreciated!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
notice my suggestion can cause an exception if the resulting text is larger than the buffer capacity.
ASKER
First off MetaTrader won't allow you to define a signed char buffer[200] ; inside the script
What I did instead was to just define a string buffer=""; inside the script and pass that.
However now after every cycle it doesn't reset the buffer and the comments keep extending out...
I even tried setting the buffer=""; everything the script runs and it still has extra data when it returns a value.
Something strange is going on here..
On a side note I talked to a friend who mention maybe writing a COM interface(DLL) and both applications using this dll to pass information...
I'm confused on the best way to do this
What I did instead was to just define a string buffer=""; inside the script and pass that.
However now after every cycle it doesn't reset the buffer and the comments keep extending out...
I even tried setting the buffer=""; everything the script runs and it still has extra data when it returns a value.
Something strange is going on here..
On a side note I talked to a friend who mention maybe writing a COM interface(DLL) and both applications using this dll to pass information...
I'm confused on the best way to do this
ASKER
Changed solution, but I will award points anyways.
define some buffer somewhre as:
byte[] buffer = new byte[someSize];
then to invoke your dll, create an unsafe function:
public unsafe void yourMethod(byte[] buffer, other params....)
{
fixed (byte *b = buffer)
{
CallYourDllMethodHere(b, buffer.Length, other params....);
}
}
your dll function should be properly declared with DlllImport attribute.