1

I am trying to learn enough C# so that I can pass a strcture by reference to a C DLL; but it never gets to the "cFunction". As you can see in the cFunction, I am explicitly setting the streamSubset value to 44; but back in the c# portion it does not return "44". Here is the C code:

typedef struct s_mPlot { double price[100]; int streamSubset; } mPlot; extern "C" __declspec( dllexport ) void cFunction(mPlot *Mplot){ Mplot->streamSubset = 44;} 

// and here is the c# code

 using System; using Vibe.Function; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] public class MPLOT { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] public double [] price; public int streamSubset; } namespace Vibe.Indicator{ public class myIdx : IndicatorObject { [DllImport("C:\\Users\\joe\\mcDll.dll", CharSet = CharSet.Auto)] public static extern void cFunction( [In, MarshalAs(UnmanagedType.LPStruct)] MPLOT mPlot ); public myIdx(object _ctx):base(_ctx){} private IPlotObject plot1; protected override void Create() { MPLOT mPlot = new MPLOT(); mPlot.streamSubset = 2; cFunction(mPlot); if (mPlot.streamSubset == 44) go(); } } 

}

2
  • Please provide more info -- what do you see instead? Crash? Unexpected results? Incorrect data? Have you tried debugging it? Commented Jul 3, 2012 at 6:29
  • The C# code can't run using the debugger. Long explanation, but it is a commercial product that prevents it. Commented Jul 3, 2012 at 6:33

3 Answers 3

1

I can see the following:

  1. You almost certainly need to specify the cdecl calling convention in your DllImport attribute. Add CallingConvention=CallingConvention.Cdecl.
  2. I believe that UnmanagedType.LPStruct adds an extra level of indirection. But you are passing a C# class which is a reference type. That means you are passing a pointer to a pointer. That's one level of indirection too many. First of all remove [In, MarshalAs(UnmanagedType.LPStruct)] altogether. Then your code should work. If you switched to a struct rather than a class for MPLOT then you'd need to pass by ref to get the indirection.

I think I would have the code like this:

[StructLayout(LayoutKind.Sequential)] public struct MPLOT { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] public double [] price; public int streamSubset; } [DllImport("dllname.dll", CallingConvention=CallingConvention.Cdecl)] public static extern void cFunction( ref MPLOT mPlot ); 
Sign up to request clarification or add additional context in comments.

3 Comments

No, what you suggest does not work either. I cannot find any examples of this on the Web after searching thru dozens of pages...starting to think it can't be done.
The code in this answer definitely matches the C++ code in your question. Write yourself a little C++ DLL to prove that is so. Something that we can't see is wrong here. What you are trying to do, to marshal this struct is trivially easy to achieve.
I did what you suggested, and you are right. What I discovered is that there is a bug in the 3rd party app that is causing the problem. Thanks for your help.
0

Try specifying the calling convention explicitly:

 [DllImport("C:\\Users\\joe\\mcDll.dll", CallingConvention=CallingConvention.Cdecl CharSet = CharSet.Auto)] 

VC exports with calling convention cdecl by default, but DllImport uses stdcall by default. So you have to specify at least one of them explicitly, or better, both.

2 Comments

Tried adding that, and I get this cryptic message (from the commercial product, not vs2010): "Object reference not set to an instance of an object"
@user994179 That is weird. Then i think you need to use stdcall on your C++ Dll.
0

Replace [In, MarshalAs(UnmanagedType.LPStruct)] with ref.

1 Comment

OK, so it now reads: "public static extern void cFunction( ref MPLOT mPlot )" I also had to add "ref" keyword to the param list where I call cFunction: "cFunction(ref mPlot)". Still same error: "Object ref not set to an instance of an object."

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.