Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
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 22-Aug-12 5:10am
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

few ideas will get you started:
char* :

    string PrefIn ="mypref";
    unsafe
    {
    
        IntPtr ptrPrefIn = Marshal.StringToHGlobalAnsi(PrefIn);
        char* _ptrPrefIn = (char*)ptrPrefIn.ToPointer();
    }
    
Structure:
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
  Permalink  
v2
Comments
Kuthuparakkal at 22-Aug-12 13:03pm
   
Not sure if the marshalling get correct size if your structure has derived types.
dsandru1 at 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..
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

I figured out how to do this.
 
I changed my struct to look like this:
[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);
  Permalink  

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

  Print Answers RSS
0 OriginalGriff 406
1 /\jmot 180
2 Suraj Sahoo | Coding Passion 170
3 BillWoodruff 159
4 Afzaal Ahmad Zeeshan 154
0 OriginalGriff 8,344
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,634
3 Maciej Los 5,024
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web02 | 2.8.1411023.1 | Last Updated 24 Aug 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100