Click here to Skip to main content
15,886,807 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have a DLL that I have imported using P/Invoke and I am trying to pass a structure of character pointers to. DataIn will be filled with an array of hex bytes, and DataOut will be filled during the AssembleSecurityPacket(). I am having trouble getting the dll to fill the output array, DataOut. It always returns with 0's.

C# Code

[StructLayout(LayoutKind.Sequential)]
    public class sSecurityLayer
    {
        public byte Header_no;
        public byte Code;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
        public byte[] DataIn;
        public int DataInLen;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 300)]
        public byte[] DataOut;
        public int DataOutLen;
        public byte AckNak;
    }
    static class Program
    {
        [DllImport("SecurityLayerDLL.dll", CharSet = CharSet.Auto, 
                                           SetLastError = true, 
                                           CallingConvention = CallingConvention.Cdecl)]
        public static extern void AssembleDataPacket([In, MarshalAs(UnmanagedType.LPStruct)]
                                                         sSecurityLayer test);
        [DllImport("SecurityLayerDLL.dll")]
        static extern void DisAssembleDataPacket([In, MarshalAs(UnmanagedType.LPStruct)]
                                                         sSecurityLayer test);
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            sSecurityLayer mySecLayer = new sSecurityLayer();
            mySecLayer.Header_no = 0x01;
            mySecLayer.DataInLen = 5;
            mySecLayer.DataIn = new byte[] {0x01,0x02,0x03,0x04,0x05};
            mySecLayer.DataOutLen = 300;
            mySecLayer.DataOut = new byte[300];
            mySecLayer.AckNak = 0x00;

            AssembleDataPacket(mySecLayer);
            //DisAssembleDataPacket(mySecLayer);
            //Application.EnableVisualStyles();
            //Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new Form1());
        }
    }
}


DLL Header

typedef struct
{          
   BYTE Header_no;
   BYTE Code;
   BYTE *DataIn;
   WORD DataInLen;
   BYTE *DataOut;
   WORD DataOutLen;
   BYTE AckNak;
}sSecurityLayer;

extern "C" __declspec(dllexport) void AssembleDataPacket(sSecurityLayer *SLayerDataPtr);
extern "C" __declspec(dllexport) void DisAssembleDataPacket(sSecurityLayer *SLayerDataPtr);


DLL Function
void AssembleDataPacket(sSecurityLayer *SLayerDataPtr)
{
	SLayerDataPtr->DataIn[0] = 0xAA;
	return;

}

Everything is in one project and it compiles and executes to the end, but when I check the DataOut in the compiler, all the values are 0, and I would expect DataOut[0] to be 0xAA.
Posted

few ideas will get you started:
char* :

C#
string PrefIn ="mypref";
unsafe
{

    IntPtr ptrPrefIn = Marshal.StringToHGlobalAnsi(PrefIn);
    char* _ptrPrefIn = (char*)ptrPrefIn.ToPointer();
}

Structure:
C#
object	_oStruct ; // some strcuture

// This function copys the structure data into a byte[]
byte[] buffer = new byte[Marshal.SizeOf(_oStruct)]; //Set the buffer ot the correct size
GCHandle h = GCHandle.Alloc(buffer , GCHandleType.Pinned); //Allocate the buffer to memory and pin it so that GC cannot use the space (Disable GC)
Marshal.StructureToPtr(_oStruct, h.AddrOfPinnedObject(), false); // copy the struct into int byte[] mem alloc
 
Share this answer
 
v2
Comments
Kuthuparakkal 22-Aug-12 13:03pm    
Not sure if the marshalling get correct size if your structure has derived types.
dsandru1 22-Aug-12 13:31pm    
So I need to allocate memory on the C# side to a static location so the dll can access and modify the array? Also I am going to be passing in an array of byte values, 0x01, 0x03, etc..
I figured out how to do this.

I changed my struct to look like this:
C#
[StructLayout(LayoutKind.Sequential)]
public class sSecurityLayer
{
    public byte Header_no;
    public byte Code;
    [MarshalAs(UnmanagedType.LPStr)]
    public string DataIn;
    public int DataInLen;
    [MarshalAs(UnmanagedType.LPStr)]
    public string DataOut;
    public int DataOutLen;
    public byte AckNak;
}


and to use the function I just converted a byte[] into a string

sSecurityLayer mySecLayer = new sSecurityLayer();
Encoding enc = Encoding.GetEncoding(1252);
string s = enc.GetString(data);
mySecLayer.Header_no = header;
mySecLayer.DataInLen = data.Length;
mySecLayer.DataIn = s;
mySecLayer.DataOut = string.Empty;
mySecLayer.AckNak = 0;

AssembleDataPacket(mySecLayer);
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900