Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. .NET (Core and Framework)
  4. managed c++.net: allocating the memory for an array of struct in a coherent memory area

managed c++.net: allocating the memory for an array of struct in a coherent memory area

Scheduled Pinned Locked Moved .NET (Core and Framework)
csharpc++helpdata-structuresperformance
4 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    HUMPPAAA
    wrote on last edited by
    #1

    Hi, first of all, plz excuse my rusty english ;) I'm writing a little wrapper in c++ .net which allows me to access some old unmanaged win32 c++ dlls from a c# program. There is one function in the dll which drives my crazy. It wants an array of struct as an argument, called by reference. Its code is looking like that (a bit simplified): the struct in c++.net and in the dll code: struct ParaList { BYTE adress; WORD length; }; the dll function prototype (in the dll -> non c++.net): BOOL RequestValues(ParaList list[], int listlength); I included it into my c++ .net like following code: [DllImport("mydll.dll",EntryPoint="_RequestValues@12")] extern "C" bool_cdecl RequestValues(ParaList *list, int listlength); What it does is: I can request the values of some parameters by executing the RequestValues() function. After that I can read the requested values by executing a readfunction(). I'm calling the function in managed c++.net like that: ParaList list[8]; list[0].adress = 0x1; list[0].length = 0x1; bool error = RequestValues(list, 1); //querying for one parameter value The problem now is: when the list only has one parameter (like in the example above) the function works correct. But when I request more than one parameter, the dll will put out some error. In a c++ mfc example the dll is working correct! I think the problem is related in the memory management of c++.net. I'm pretty new to c++.net. Am I right that in managed c++.net the allocated memory for an array must not be in sequence? So the single elements of the array are distributed all over the memory? In that case the dll would get only the pointer on the first array element but the second element is not the neighbour, so the dll reads garbage when it wants to read the data of the second array element. I tried a few things with __pin and __nogc keywords which led to nothing :( Does anyone have a clue how I can tell c++.net to allocate the memory for the array in a coherent memory area? Thanks for reading this! ~Sepp

    C 1 Reply Last reply
    0
    • H HUMPPAAA

      Hi, first of all, plz excuse my rusty english ;) I'm writing a little wrapper in c++ .net which allows me to access some old unmanaged win32 c++ dlls from a c# program. There is one function in the dll which drives my crazy. It wants an array of struct as an argument, called by reference. Its code is looking like that (a bit simplified): the struct in c++.net and in the dll code: struct ParaList { BYTE adress; WORD length; }; the dll function prototype (in the dll -> non c++.net): BOOL RequestValues(ParaList list[], int listlength); I included it into my c++ .net like following code: [DllImport("mydll.dll",EntryPoint="_RequestValues@12")] extern "C" bool_cdecl RequestValues(ParaList *list, int listlength); What it does is: I can request the values of some parameters by executing the RequestValues() function. After that I can read the requested values by executing a readfunction(). I'm calling the function in managed c++.net like that: ParaList list[8]; list[0].adress = 0x1; list[0].length = 0x1; bool error = RequestValues(list, 1); //querying for one parameter value The problem now is: when the list only has one parameter (like in the example above) the function works correct. But when I request more than one parameter, the dll will put out some error. In a c++ mfc example the dll is working correct! I think the problem is related in the memory management of c++.net. I'm pretty new to c++.net. Am I right that in managed c++.net the allocated memory for an array must not be in sequence? So the single elements of the array are distributed all over the memory? In that case the dll would get only the pointer on the first array element but the second element is not the neighbour, so the dll reads garbage when it wants to read the data of the second array element. I tried a few things with __pin and __nogc keywords which led to nothing :( Does anyone have a clue how I can tell c++.net to allocate the memory for the array in a coherent memory area? Thanks for reading this! ~Sepp

      C Offline
      C Offline
      Christian Graus
      wrote on last edited by
      #2

      It's easier to use pinvoke to call functions from c++ dlls. There is a C++/CLI forum, if you ask there, Nish is bound to find it and help you.

      Christian Graus - C++ MVP 'Why don't we jump on a fad that hasn't already been widely discredited ?' - Dilbert

      H 1 Reply Last reply
      0
      • C Christian Graus

        It's easier to use pinvoke to call functions from c++ dlls. There is a C++/CLI forum, if you ask there, Nish is bound to find it and help you.

        Christian Graus - C++ MVP 'Why don't we jump on a fad that hasn't already been widely discredited ?' - Dilbert

        H Offline
        H Offline
        HUMPPAAA
        wrote on last edited by
        #3

        Hi, thank you for your reply! Finally I found the problem by my own. The problem was the structure: struct TMP { DWORD x; WORD z; }; A sizeof(TMP) told me that it's 8 Bytes big. The strange thing here is that a DWORD is 4 Bytes and a WORD is 2 Bytes big (confirmed by sizeof(DWORD) and sizeof(WORD). If you count it together it's 6 and not 8??? The DLL function expected an array of 6 Bytes structs. What it got was an array of 8 Bytes structs, which led to that the Dll got garbage while it was reading the second array element. What I did now, was splitting up the DWORD into two WORD variables: struct TMP2 { WORD x1; WORD x2; WORD z; }; sizeof(TMP2) says that it's 6 Bytes big now. Really strange.

        L 1 Reply Last reply
        0
        • H HUMPPAAA

          Hi, thank you for your reply! Finally I found the problem by my own. The problem was the structure: struct TMP { DWORD x; WORD z; }; A sizeof(TMP) told me that it's 8 Bytes big. The strange thing here is that a DWORD is 4 Bytes and a WORD is 2 Bytes big (confirmed by sizeof(DWORD) and sizeof(WORD). If you count it together it's 6 and not 8??? The DLL function expected an array of 6 Bytes structs. What it got was an array of 8 Bytes structs, which led to that the Dll got garbage while it was reading the second array element. What I did now, was splitting up the DWORD into two WORD variables: struct TMP2 { WORD x1; WORD x2; WORD z; }; sizeof(TMP2) says that it's 6 Bytes big now. Really strange.

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          There is nothing really strange about that, C (and C++ I guess) pads all its structs so all elements are "naturally aligned" (to an adr that is a multiple of their size), and aligns the entire struct to the size of the largest element, in your case 4B due to the DWORD/int. The reason is the compiler can then emit code that manipulates 4B quantities without worrying about alignment and/or achieving highest performance. (Some processors do not know how to load a DWORD from an unaligned adr, others do but take more time to do it). The net result is: 1) if your struct's size is not a multiple of 4 but contains elements sized 4B, the struct will act as if its size is a multiple of 4B (even when sizeof shows otherwise). 2) if the elements in your struct are not "naturally aligned", the struct will be padded with extra bytes to achieve the natural alignment (=each element gets aligned according to its size). So struct { byte a; // offset 0 short b; // 1 ? not naturally aligned byte c; // 3 ? OK byte d; // 4 ? OK long e; // 5 ? not naturally aligned } gets compiled as if it were: struct { byte a; // offset 0 byte bDummy; short b; // offset 2 byte c; // offset 4 byte d; // offset 5 byte eDummy1; byte eDummy2; long e; // offset 8 } The function you used was an old one, relying on a stride of 6B, so something special needed to be done. In C (and C++ I guess) there are compiler switches and/or pragmas to disable the alignment/padding. In C# your splitting the 4B into two 2B elements is probably the best way to get what you needed. :)

          Luc Pattyn

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups