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. C#
  4. Calling unmanged DLL

Calling unmanged DLL

Scheduled Pinned Locked Moved C#
csharpjsonquestion
6 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.
  • A Offline
    A Offline
    Andy Davey
    wrote on last edited by
    #1

    When you have to call an unmanged API method that requires a structure that contains a fixed length string, how should you express that in C# EG: A method I want to call has this unmanaged structure: typedef struct foo {   char szSymbol[20];   DWORD dwVolume; } FOO; So in C# I think I would do this: [StructLayout(LayoutKind.Sequential, Pack=4, CharSet=CharSet.Ansi)] struct FOO {   public string szSymbol = new String(' ', 20);   public UInt32 dwVolume; } Am I on the right track? Andy

    A J 2 Replies Last reply
    0
    • A Andy Davey

      When you have to call an unmanged API method that requires a structure that contains a fixed length string, how should you express that in C# EG: A method I want to call has this unmanaged structure: typedef struct foo {   char szSymbol[20];   DWORD dwVolume; } FOO; So in C# I think I would do this: [StructLayout(LayoutKind.Sequential, Pack=4, CharSet=CharSet.Ansi)] struct FOO {   public string szSymbol = new String(' ', 20);   public UInt32 dwVolume; } Am I on the right track? Andy

      A Offline
      A Offline
      Andy Davey
      wrote on last edited by
      #2

      Crap - it would appear that you can't initalise structures like that. He who knows and knows that he knows, is wise;  follow him_He who knows and knows not that he knows, is asleep;_  wake him_He who knows not, and knows that he knows not, is simple;_  teach him_He whoe knows not and knows not that he knows not, is a fool;_  kick him

      1 Reply Last reply
      0
      • A Andy Davey

        When you have to call an unmanged API method that requires a structure that contains a fixed length string, how should you express that in C# EG: A method I want to call has this unmanaged structure: typedef struct foo {   char szSymbol[20];   DWORD dwVolume; } FOO; So in C# I think I would do this: [StructLayout(LayoutKind.Sequential, Pack=4, CharSet=CharSet.Ansi)] struct FOO {   public string szSymbol = new String(' ', 20);   public UInt32 dwVolume; } Am I on the right track? Andy

        J Offline
        J Offline
        James T Johnson
        wrote on last edited by
        #3

        Use the MarshalAs attribute on the struct's fields to specify how it should convert the string. Untested/uncompiled:

        [StructLayout(LayoutKind.Sequential, Pack=4, CharSet=CharSet.Ansi)]
        struct FOO
        {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=20)]
        public string szSymbol;
        public uint dwVolume;
        }

        Now if szSymbol is going to be modified by the P/Invoke'd method then you need to use a StringBuilder rather than string to avoid any problems that may occur due to string interning. James "It is self repeating, of unknown pattern" Data - Star Trek: The Next Generation

        A 1 Reply Last reply
        0
        • J James T Johnson

          Use the MarshalAs attribute on the struct's fields to specify how it should convert the string. Untested/uncompiled:

          [StructLayout(LayoutKind.Sequential, Pack=4, CharSet=CharSet.Ansi)]
          struct FOO
          {
          [MarshalAs(UnmanagedType.ByValTStr, SizeConst=20)]
          public string szSymbol;
          public uint dwVolume;
          }

          Now if szSymbol is going to be modified by the P/Invoke'd method then you need to use a StringBuilder rather than string to avoid any problems that may occur due to string interning. James "It is self repeating, of unknown pattern" Data - Star Trek: The Next Generation

          A Offline
          A Offline
          Andy Davey
          wrote on last edited by
          #4

          Thanks heaps - I had just discovered this attribute myself but was going to use UnmanagedType.LPStr James T. Johnson wrote: Now if szSymbol is going to be modified by the P/Invoke'd method then you need to use a StringBuilder rather than string to avoid any problems that may occur due to string interning Rrrright. Could you elaborate on the StringBuilder part? The szSymbol is going to be modified by the P/Invoke'd method. TIA Andy

          J L 2 Replies Last reply
          0
          • A Andy Davey

            Thanks heaps - I had just discovered this attribute myself but was going to use UnmanagedType.LPStr James T. Johnson wrote: Now if szSymbol is going to be modified by the P/Invoke'd method then you need to use a StringBuilder rather than string to avoid any problems that may occur due to string interning Rrrright. Could you elaborate on the StringBuilder part? The szSymbol is going to be modified by the P/Invoke'd method. TIA Andy

            J Offline
            J Offline
            James T Johnson
            wrote on last edited by
            #5

            Andy Davey wrote: I had just discovered this attribute myself but was going to use UnmanagedType.LPStr I'm not that familiar with interop but to me LPStr means a pointer to a string rather than embedding one within a struct. I think this is also how the Interop Marshaller will interpret it. Andy Davey wrote: Could you elaborate on the StringBuilder part? Sure. Strings in .NET are considered immutable; this allows for some optimizations to be made in both memory requirements and when comparing strings. Because they are immutable you can have two strings that contain the same value point to the same block of memory. And rather than compare every single character to see if they are equal you can just compare whether the two strings point to the same object. That is where string-interning comes in, it takes a string and adds it to an internal table which allows you to make use of those optimizations. But there is a down side to strings being immutable. When you want to do lots of string operations (such as concatenation) you create a lot of new string objects using up memory that isn't used after the next operation. That is where the StringBuilder comes in (full name: System.Text.StringBuilder) it maintains an internal buffer/array of characters (similar to C style strings) and does various operations on the array rather than creating new string objects. When you are done modifying the StringBuilder you can then call .ToString() on it and get out the string that was built. To link this in with P/Invoke, since you have a buffer that needs a string the proper usage is to supply that buffer with a StringBuilder object rather than a string (which isn't supposed to change). To change the first struct (going from memory):

            [StructLayout(Layout.Sequential, Pack=4, CharSet=CharSet.Ansi)]
            struct FOO
            {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst=20)]
            public System.Text.StringBuilder szSymbol;
            public uint dwVolume;
            }

            Then, because structs can't have default constructors you need to initialize szSymbol to szSymbol = new System.Text.StringBuilder(20); To provide a default constructor you can change FOO from a struct to a class (despite its name StructLayout can be applied to classes :)) HTH, James "It is self repeating, of unknown pattern" Data - Star Trek: The Next Generation

            1 Reply Last reply
            0
            • A Andy Davey

              Thanks heaps - I had just discovered this attribute myself but was going to use UnmanagedType.LPStr James T. Johnson wrote: Now if szSymbol is going to be modified by the P/Invoke'd method then you need to use a StringBuilder rather than string to avoid any problems that may occur due to string interning Rrrright. Could you elaborate on the StringBuilder part? The szSymbol is going to be modified by the P/Invoke'd method. TIA Andy

              L Offline
              L Offline
              leppie
              wrote on last edited by
              #6

              I only saw this last night, but in the lastest MSDN they a very comprehensive Marshalling Tutorial :) Hey leppie! Your "proof" seems brilliant and absurd at the same time. - Vikram Punathambekar 28 Apr '03

              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