pointer to struct passing
Hi everyone, I have a hopefully simple problem. I've written a dll in C++ (unmanaged, UNICODE). The dll takes care of all of the threading and the memory management. The format of my C++ struct is:
Code:
struct OSDParam{
wchar_t* userfont;
int fontsize;
int Monitor;
int Displength;
int alpha;
wchar_t* text;
int Coloring[3];
float x;
float y;
int fontstyle;
HANDLE procHand;
OSDParam()
{
userfont = L"Times New Roman";
fontsize = 45;
Monitor = 2;
Displength = 5;
alpha = 255;
text = L"No text set for OSD";
Coloring[0]= 0;
Coloring[1] = 0;
Coloring[2] = 0;
x = 0.0;
y = 0.0;
fontstyle = 0;
HANDLE procHand = NULL;
}
};
I have a CreateParam function that takes a NULL pointer from a client program and supplies it with an address and default values. In C++ code (which works) it looks like
Code:
OSDParam* params = NULL;
CreateParam(params);
This works very well. Now, I'm trying to create a client program in C# and I can't seem to provide an address for the struct. It runs, but the values passed to the client are incorrect and frequently ridiculous. This would seem to imply that I'm just randomly accessing memory and not assigning it like one does in C++. The test code follows below. If anyone has any ideas how I can assign the address through the CreateParam function, please let me know.
~Steve
Code:
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApplication1
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OSDParam
{
public String userfont;
public int fontsize;
public int Monitor;
public int Displength;
public int alpha;
public String text;
public int[] Coloring;
public float x;
public float y;
public int fontstyle;
}
/// <summary>
/// Summary description for Class1.
/// </summary>
///
public class OSDdll
{
[DllImport("OSD.dll")]
public static extern int InitOSD();
[DllImport("OSD.dll")]
public static extern int ExitOSD();
[DllImport("OSD.dll")]
public static extern int CreateParam(ref OSDParam Parameters);
[DllImport("OSD.dll")]
public static extern int SemiPermText(OSDParam Parameters);
}
class Class1
{
[STAThread]
static void Main(string[] args)
{
OSDParam t = new OSDParam();
OSDdll.InitOSD();
//Pass the address to the struct that my dll manages
OSDdll.CreateParam(ref t);
Console.WriteLine(t.fontsize);
OSDdll.ExitOSD();
}
}
}
Re: pointer to struct passing
Hello diehardii,
I am a c++ programmer who is trying to move on c#, without having to return to school. And I have exactely the same problem than you.
Could you please tell me if you finally solved this problem ?
And if yes, could you please explain how ?
Thank you.
Re: pointer to struct passing
Don't you need to use the Interop.Marshal functions to allocate unmanaged memory to your C# client. Eg
(This code is lifted from an article I found that allows me to use the 'Select Users or Groups' dialog from within my c# apps)
Code:
/// <summary>
/// The DSOP_SCOPE_INIT_INFO structure describes one or more scope types that have the same attributes. A scope type is a type of location, for example a domain, computer, or Global Catalog, from which the user can select objects.
/// A scope type is a type of location, for example a domain, computer, or Global Catalog, from which the user can select objects.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto), Serializable]
public struct DSOP_SCOPE_INIT_INFO
{
public uint cbSize;
public uint flType;
public uint flScope;
[MarshalAs(UnmanagedType.Struct)]
public DSOP_FILTER_FLAGS FilterFlags;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwzDcName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwzADsPath;
public uint hr;
}
DSOP_SCOPE_INIT_INFO[] scopeInitInfo = new DSOP_SCOPE_INIT_INFO[2];
// Initialize 1st search scope
scopeInitInfo[0].cbSize = (uint)Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO));
scopeInitInfo[0].flType = DSOP_SCOPE_TYPE_FLAGS.DSOP_SCOPE_TYPE_GLOBAL_CATALOG; //Convert.ToUInt32("3FE",16);
scopeInitInfo[0].flScope = DSOP_SCOPE_INIT_INFO_FLAGS.DSOP_SCOPE_FLAG_DEFAULT_FILTER_COMPUTERS + 1; // Starting !?
scopeInitInfo[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_COMPUTERS + 1; // +1 = advanced view, Check MSDN for the available options
scopeInitInfo[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FLAGS.DSOP_DOWNLEVEL_FILTER_COMPUTERS;
scopeInitInfo[0].pwzADsPath = null;
scopeInitInfo[0].pwzDcName = null;
scopeInitInfo[0].hr = 0;
// Allocate memory from the unmananged mem of the process, this should be freed later
IntPtr refScopeInitInfo = Marshal.AllocHGlobal(Marshal.SizeOf (typeof (DSOP_SCOPE_INIT_INFO)) * 2);
// Marshal structs to pointers
Marshal.StructureToPtr (scopeInitInfo[0], refScopeInitInfo,true);
Re: pointer to struct passing
Thank you for your help. Yes I am convinced that I have to use the Interop.Marshal functions. I already tried similar code during several hours, without success.
I am looking hopelessly for somebody who did it !