0

Consider the Following structure

 /*Structure defined in unmanaged dll written in cpp*/
 struct NSCASR_RCG_RES_ST
 {
 unsigned int ulSizeBytes;
 unsigned int ulWarnings;
 unsigned short usNumPhrases;
 wchar_t* pstrWaveformURI;
 unsigned int ulWaveformSizeBytes;
 unsigned int ulWaveformDuration;
 };

 /*Structure defined in c#*/
 struct NSCASR_RCG_RES_ST
 {

 unsigned int ulSizeBytes;
 unsigned int ulWarnings;
 unsigned short usNumPhrases;
 String pstrWaveformURI;
 unsigned int ulWaveformSizeBytes;
 unsigned int ulWaveformDuration;
 };

In my unmagaed DLL(cpp) I am calling the fucntion by passng the address of the structure as follows :

 NSCASR_RCG_RES_ST result_recognize;
 ASR_Recognize_ResultsGet(&result_recognize);

In my managed DLL the definition is like

 void ASR_Recognize_ResultsGet(NSCASR_RCG_RES_ST *recognize)
 {
 /*MRCP_MD_TO_ASR is namespace and Constants is class name
   which consists of structure NSCASR_RCG_RES_ST */

    MRCP_MD_TO_ASR::Constants::NSCASR_RCG_RES_ST *pRecognitionResults;
    pRecognitionResults = (MRCP_MD_TO_ASR::Constants::NSCASR_RCG_RES_ST *)recognize;
    MRCP_MD_TO_ASR::ASR_API::ASR_Recognize_ResultsGet(*pRecognitionResults);
 }

In c# code I am assigning the following members

 public static int ASR_Recognize_ResultsGet(ref Constants.NSCASR_RCG_RES_ST pRecognitionResults)
 {
     pRecognitionResults = speech_results;
     pRecognitionResults.ulSizeBytes = 200;
     return 0;
 }

But when I see the content of result_recognize after execution of statement the value 200 is getting assigned to usNumPhrases variable instead of ulSizeBytes

  • Short/long/string all (potentially) have different sizes depending on the compiler switches you are using (64-bit int may be different to 32-bit unsigned int) and the padding between those fields may also be compiler dependent (e.g. 64 bit compiler may align a short to an 8 byte boundary). – Neil Sep 01 '18 at 10:30
  • what may be the solution – Akshay Kanagali Sep 01 '18 at 10:40
  • You should decorate C# struct with `StructLayout` and `FieldOffset` attributes, because otherwise CLR is allowed to arbitrarily reorder struct's fields so that their offsets don't match with C++ struct. See for example [here](https://stackoverflow.com/questions/15392054/net-behaviour-of-layoutkind-explicit-for-a-field-which-is-itself-a-struct) – Ňuf Sep 01 '18 at 10:45
  • Shall I get some resource to refer the Structlayout and Fieldoffset. The provided link doesn't have much information – Akshay Kanagali Sep 01 '18 at 11:07
  • Official documentation for [StructLayout](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.structlayoutattribute?view=netframework-4.7.2) and [FieldOffset](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.fieldoffsetattribute?view=netframework-4.7.2) should help. – Ňuf Sep 01 '18 at 11:17

1 Answers1

0

I got the solution by adding structlayout as explicit and using charset as c# uses unicode 16 , we have to make it unicode 8 if we are using IntPtr concepts

 [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
    public struct NSCASR_RCG_PHRASE_ST
    {
        [FieldOffset(0)]
        public ushort usConfidence;
        [FieldOffset(2)]
        public ushort usNumItems;
        [FieldOffset(4)]
        public short sGrammarIndex;
        [FieldOffset(6)]
        public short sGrammarType;
    }


    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
    public unsafe struct NSCASR_RCG_RES_ST
    {

        [FieldOffset(0)]
        public uint ulSizeBytes;
        [FieldOffset(4)]
        public uint ulWarnings;
        [FieldOffset(8)]
        public ushort usNumPhrases;
        [FieldOffset(12)]
        public IntPtr pstrWaveformURI;
        [FieldOffset(16)]
        public uint ulWaveformSizeBytes;
        [FieldOffset(20)]
        public uint ulWaveformDuration;
    }