Passing a pointer to a structure as a parameter in C #

I have a function in C ++ that I exported to a DLL. I contain a struct pointer as one of the parameters. I need to use this function in C #, so I used DLLImport for this function and recreated the structure in C # using StructLayout. I tried passing a parameter using ref, and also tried using Marshaling in using MarshalAs (UnmangedType.Struct) and Marshal.PtrToStructure. The parameter still does not pass correctly.

Example:

[DllImport("testdll.dll")]
public static extern int getProduct(int num1, int num2, [MarshalAs(UnmanagedType.Struct)] ref test_packet tester);

Another tidbit of information, the structure contains a * var byte, which I think can cause a problem in terms of passing param as ref. Any ideas? Am I on the right track? Thanks for the help.

Thanks nobugz for the answer. Here's a sample def structure:

//C# DEFINITION 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 

public struct test_packet 
{ 

     public UInt32 var_alloc_size; 

    public byte* var; 

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_TAG_LENGTH)] 
    public byte[] tag; 

} 

//ORIGINAL UNMANAGED STRUCT

typedef struct test_packet_tag 
{

    unsigned int var_alloc_size;

    unsigned char *var;

    unsigned char tag[MAX_TAG_LENGTH];
} test_packet;
+3
3

"ref" , [MarshalAs]. - , , . , .


DllImportAttribute.CharSet , CharSet.Ansi. "var" , []. :

 var product = new test_packet();
 product.var_alloc_size = 666;    // Adjust as needed
 product.var = new byte[product.var_alloc_size];
 int retval = getProduct(42, 43, ref product);

, , .

+4

. . , , , #. . , . , ptrs ( ). , , . .

sig -

  [DllImport("stochfitdll.dll", EntryPoint = "Init", ExactSpelling = false,  CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
    public static extern void Init([MarshalAs(UnmanagedType.LPStruct)] ModelSettings settings);

++

#pragma pack(push, 8)
struct ReflSettings
{
    LPCWSTR Directory;
    double* Q;
    double* Refl;
    double* ReflError;
    double* QError;
    int QPoints;
    double SubSLD;
    double FilmSLD;
    double SupSLD;
    int Boxes;
    double FilmAbs;
    double SubAbs;
    double SupAbs;
    double Wavelength;
    BOOL UseSurfAbs;
    double Leftoffset;
    double QErr;
    BOOL Forcenorm;
    double Forcesig;
    BOOL Debug;
    BOOL XRonly;
    int Resolution;
    double Totallength;
    double FilmLength;
    BOOL Impnorm;
    int Objectivefunction;
    double Paramtemp;
    LPCWSTR Title;

 };
 #pragma pack(pop)

# -

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 8)]
public class ModelSettings:IDisposable
{
    #region Variables

    public string Directory;
    public IntPtr Q;
    public IntPtr Refl;
    public IntPtr ReflError;
    public IntPtr QError;
    public int QPoints;
    public double SubSLD;
      public double SurflayerSLD;
        public double SupSLD;
         public int Boxes;
         public double SurflayerAbs;
         public double SubAbs;
       public double SupAbs;
        public double Wavelength;
         public bool UseAbs;
         public double SupOffset;
     public double Percerror;
       public bool Forcenorm;
         public double Forcesig;
         public bool Debug;
         public bool ForceXR;
    public int Resolution;
    public double Totallength;
    public double Surflayerlength;
    public bool ImpNorm;
    public int FitFunc;
    public double ParamTemp;
    public string version = "0.0.0";

    [XmlIgnoreAttribute] private bool disposed = false;

#endregion

    public ModelSettings()
    { }

    ~ModelSettings()
    {
        Dispose(false);
    }


    #region Public Methods
    public void SetArrays(double[] iQ, double[] iR, double[] iRerr, double[] iQerr)
    {
        //Blank our arrays if they hold data
        if (Q == IntPtr.Zero)
            ReleaseMemory();

        int size = Marshal.SizeOf(iQ[0]) * iQ.Length;

            try
            {
                QPoints = iQ.Length;
                Q = Marshal.AllocHGlobal(size);
                Refl = Marshal.AllocHGlobal(size);
                ReflError = Marshal.AllocHGlobal(size);

                if (iQerr != null)
                    QError = Marshal.AllocHGlobal(size);
                else
                    QError = IntPtr.Zero;

                Marshal.Copy(iQ, 0, Q, iQ.Length);
                Marshal.Copy(iR, 0, Refl, iR.Length);
                Marshal.Copy(iRerr, 0, ReflError, iRerr.Length);

                if (iQerr != null)
                    Marshal.Copy(iQerr, 0, QError, iQerr.Length);
            }
            catch (Exception ex)
            {
               //error handling
            }
    }
    #endregion

    #region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            // Call the appropriate methods to clean up
            // unmanaged resources here.
            // If disposing is false,
            // only the following code is executed.
            ReleaseMemory();
            // Note disposing has been done.
            disposed = true;
        }
    }

    private void ReleaseMemory()
    {
        if (Q != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(Q);
                Marshal.FreeHGlobal(Refl);
                Marshal.FreeHGlobal(ReflError);

                if (QError != IntPtr.Zero)
                    Marshal.FreeHGlobal(QError);
            }
    }

    #endregion
}
+1

P/Invoke , UnmanagedType.Struct. , , #. , ++?

0

Source: https://habr.com/ru/post/1733545/


All Articles