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. 64-bit Interop

64-bit Interop

Scheduled Pinned Locked Moved .NET (Core and Framework)
helpc++comjsonquestion
12 Posts 4 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.
  • L Offline
    L Offline
    Leslie Sanford
    wrote on last edited by
    #1

    I was running one of my assemblies through FxCop and got this message: "As it is declared in your code, parameter 'handle' of PInvoke NativeMethods.waveOutGetVolume(Int32, Int32&):Int32 will be 4 bytes wide on 64-bit platforms. This is not correct, as the actual native declaration of this API indicates it should be 8 bytes wide on 64-bit platforms. Consult the MSDN Platform SDK documentation for help determining what data type should be used instead of 'System.Int32'." I've been looking at MSDN and haven't found anything yet specific to this problem. Still looking. But I thought I'd go ahead and ask here. How do you declare your interop methods so that they work correctly on both 32-bit and 64-bit systems?

    A 1 Reply Last reply
    0
    • L Leslie Sanford

      I was running one of my assemblies through FxCop and got this message: "As it is declared in your code, parameter 'handle' of PInvoke NativeMethods.waveOutGetVolume(Int32, Int32&):Int32 will be 4 bytes wide on 64-bit platforms. This is not correct, as the actual native declaration of this API indicates it should be 8 bytes wide on 64-bit platforms. Consult the MSDN Platform SDK documentation for help determining what data type should be used instead of 'System.Int32'." I've been looking at MSDN and haven't found anything yet specific to this problem. Still looking. But I thought I'd go ahead and ask here. How do you declare your interop methods so that they work correctly on both 32-bit and 64-bit systems?

      A Offline
      A Offline
      Abisodun
      wrote on last edited by
      #2

      Use IntPtr in place of Int32.

      L 1 Reply Last reply
      0
      • A Abisodun

        Use IntPtr in place of Int32.

        L Offline
        L Offline
        Leslie Sanford
        wrote on last edited by
        #3

        Abisodun wrote:

        Use IntPtr in place of Int32.

        But does this mean having to allocate unmanaged memory for the pointer? If I do this:

        IntPtr handle = new IntPtr();

        int result = waveOutOpen(handle, deviceID, ref format, 0, 0, CALLBACK_NULL);

        waveOutOpen returns an error. If I have to allocate unmanaged memory for the pointer (ugh), how do I tell how much to allocate? On a 32-bit system it will be 4 bytes. On a 64-bit system it will be 8 bytes. [EDIT] Nevermind. I discovered that I need to declare my interop method like this:

        [DllImport("winmm.dll")]
        public static extern int waveOutOpen(out IntPtr handle, int deviceID, ref WaveFormat format,
        int dummy, int instance, int flags);

        The key is to use the out modifier on the IntPtr parameter. Thanks for your help. :) [/EDIT] -- modified at 13:34 Friday 17th August, 2007

        D L 2 Replies Last reply
        0
        • L Leslie Sanford

          Abisodun wrote:

          Use IntPtr in place of Int32.

          But does this mean having to allocate unmanaged memory for the pointer? If I do this:

          IntPtr handle = new IntPtr();

          int result = waveOutOpen(handle, deviceID, ref format, 0, 0, CALLBACK_NULL);

          waveOutOpen returns an error. If I have to allocate unmanaged memory for the pointer (ugh), how do I tell how much to allocate? On a 32-bit system it will be 4 bytes. On a 64-bit system it will be 8 bytes. [EDIT] Nevermind. I discovered that I need to declare my interop method like this:

          [DllImport("winmm.dll")]
          public static extern int waveOutOpen(out IntPtr handle, int deviceID, ref WaveFormat format,
          int dummy, int instance, int flags);

          The key is to use the out modifier on the IntPtr parameter. Thanks for your help. :) [/EDIT] -- modified at 13:34 Friday 17th August, 2007

          D Offline
          D Offline
          Dave Kreskowiak
          wrote on last edited by
          #4

          The size of IntPtr changes depending on the proc. So, an IntPtr on a 32-bit system is 32-bits wide and on a 64-bit system is 64-bits wide, automatically. You don't have to allocate anything. You're just using the pointer as a self-sizing integer.

          IntPtr handle = IntPtr.Zero;
          

          A guide to posting questions on CodeProject[^]
          Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
               2006, 2007

          L 1 Reply Last reply
          0
          • L Leslie Sanford

            Abisodun wrote:

            Use IntPtr in place of Int32.

            But does this mean having to allocate unmanaged memory for the pointer? If I do this:

            IntPtr handle = new IntPtr();

            int result = waveOutOpen(handle, deviceID, ref format, 0, 0, CALLBACK_NULL);

            waveOutOpen returns an error. If I have to allocate unmanaged memory for the pointer (ugh), how do I tell how much to allocate? On a 32-bit system it will be 4 bytes. On a 64-bit system it will be 8 bytes. [EDIT] Nevermind. I discovered that I need to declare my interop method like this:

            [DllImport("winmm.dll")]
            public static extern int waveOutOpen(out IntPtr handle, int deviceID, ref WaveFormat format,
            int dummy, int instance, int flags);

            The key is to use the out modifier on the IntPtr parameter. Thanks for your help. :) [/EDIT] -- modified at 13:34 Friday 17th August, 2007

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

            Hi Leslie, here is my theory (still theory since I have not run any of this on Win64): - for native pointers you really should use IntPtr, and it is not hard to do so. - Win32 uses 4B pointers, Win64 needs 8B pointers - you must build for either 32-bit or 64-bit - on Win64 everything must be consistent (all modules 64-bit is fine, and all modules 32-bit runs in some compatibility mode, not sure tho) - IntPtr is a value type that holds either 4B or 8B pointer value - IntPtr must be initialized, normally you give its value at construction - a lot of P/Invoke examples are wrong, and use int/uint where it should have been IntPtr. Most notably SendMessage: lParam, wParam and return value should be regarded as IntPtr, and cast to int or whatever if and when appropriate. - correct prototypes would have IntPtr for anything that is or could be a handle (such as lParam). Your problem seems to be you did not initialize handle. :)

            Luc Pattyn [Forum Guidelines] [My Articles]


            this weeks tips: - make Visual display line numbers: Tools/Options/TextEditor/... - show exceptions with ToString() to see all information - before you ask a question here, search CodeProject, then Google


            L 1 Reply Last reply
            0
            • D Dave Kreskowiak

              The size of IntPtr changes depending on the proc. So, an IntPtr on a 32-bit system is 32-bits wide and on a 64-bit system is 64-bits wide, automatically. You don't have to allocate anything. You're just using the pointer as a self-sizing integer.

              IntPtr handle = IntPtr.Zero;
              

              A guide to posting questions on CodeProject[^]
              Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
                   2006, 2007

              L Offline
              L Offline
              Leslie Sanford
              wrote on last edited by
              #6

              Dave Kreskowiak wrote:

              The size of IntPtr changes depending on the proc. So, an IntPtr on a 32-bit system is 32-bits wide and on a 64-bit system is 64-bits wide, automatically. You don't have al allocate anything. You're just using the pointer as a self-sizing integer.

              Understood. I think I was running into problems when I tried switching to IntPtr because I was using the ref modifier on the IntPtr parameter instead of out. Thanks for your help.

              1 Reply Last reply
              0
              • L Luc Pattyn

                Hi Leslie, here is my theory (still theory since I have not run any of this on Win64): - for native pointers you really should use IntPtr, and it is not hard to do so. - Win32 uses 4B pointers, Win64 needs 8B pointers - you must build for either 32-bit or 64-bit - on Win64 everything must be consistent (all modules 64-bit is fine, and all modules 32-bit runs in some compatibility mode, not sure tho) - IntPtr is a value type that holds either 4B or 8B pointer value - IntPtr must be initialized, normally you give its value at construction - a lot of P/Invoke examples are wrong, and use int/uint where it should have been IntPtr. Most notably SendMessage: lParam, wParam and return value should be regarded as IntPtr, and cast to int or whatever if and when appropriate. - correct prototypes would have IntPtr for anything that is or could be a handle (such as lParam). Your problem seems to be you did not initialize handle. :)

                Luc Pattyn [Forum Guidelines] [My Articles]


                this weeks tips: - make Visual display line numbers: Tools/Options/TextEditor/... - show exceptions with ToString() to see all information - before you ask a question here, search CodeProject, then Google


                L Offline
                L Offline
                Leslie Sanford
                wrote on last edited by
                #7

                Luc Pattyn wrote:

                here is my theory (still theory since I have not run any of this on Win64): - for native pointers you really should use IntPtr, and it is not hard to do so. - Win32 uses 4B pointers, Win64 needs 8B pointers - you must build for either 32-bit or 64-bit - on Win64 everything must be consistent (all modules 64-bit is fine, and all modules 32-bit runs in some compatibility mode, not sure tho) - IntPtr is a value type that holds either 4B or 8B pointer value - IntPtr must be initialized, normally you give its value at construction - a lot of P/Invoke examples are wrong, and use int/uint where it should have been IntPtr. Most notably SendMessage: lParam, wParam and return value should be regarded as IntPtr, and cast to int or whatever if and when appropriate. - correct prototypes would have IntPtr for anything that is or could be a handle (such as lParam).

                Thanks for this explanation. I've got a lot of code revision to do. I have older "toolkits" whose P/Invoke methods are apparently wrong, or will at least break on a 64-bit system.

                Luc Pattyn wrote:

                Your problem seems to be you did not initialize handle.

                Actually, I don't think I'm suppose to initialize the handle, rather I should use the out modifier on the IntPtr parameters rather than ref, as I had initially tried.

                L 1 Reply Last reply
                0
                • L Leslie Sanford

                  Luc Pattyn wrote:

                  here is my theory (still theory since I have not run any of this on Win64): - for native pointers you really should use IntPtr, and it is not hard to do so. - Win32 uses 4B pointers, Win64 needs 8B pointers - you must build for either 32-bit or 64-bit - on Win64 everything must be consistent (all modules 64-bit is fine, and all modules 32-bit runs in some compatibility mode, not sure tho) - IntPtr is a value type that holds either 4B or 8B pointer value - IntPtr must be initialized, normally you give its value at construction - a lot of P/Invoke examples are wrong, and use int/uint where it should have been IntPtr. Most notably SendMessage: lParam, wParam and return value should be regarded as IntPtr, and cast to int or whatever if and when appropriate. - correct prototypes would have IntPtr for anything that is or could be a handle (such as lParam).

                  Thanks for this explanation. I've got a lot of code revision to do. I have older "toolkits" whose P/Invoke methods are apparently wrong, or will at least break on a 64-bit system.

                  Luc Pattyn wrote:

                  Your problem seems to be you did not initialize handle.

                  Actually, I don't think I'm suppose to initialize the handle, rather I should use the out modifier on the IntPtr parameters rather than ref, as I had initially tried.

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

                  Leslie Sanford wrote:

                  Actually, I don't think I'm suppose to initialize the handle, rather I should use the out modifier on the IntPtr parameters rather than ref, as I had initially tried

                  That depends entirely on the function at hand; you typically need to provide an IntPtr or be ready to receive one (with "out" keyword). I don't recall any Win32 function that provides a handle that way, they typically use the return value (and return zero for error, then you would call GetLastError for details). Greetings

                  Luc Pattyn [Forum Guidelines] [My Articles]


                  this weeks tips: - make Visual display line numbers: Tools/Options/TextEditor/... - show exceptions with ToString() to see all information - before you ask a question here, search CodeProject, then Google


                  L 1 Reply Last reply
                  0
                  • L Luc Pattyn

                    Leslie Sanford wrote:

                    Actually, I don't think I'm suppose to initialize the handle, rather I should use the out modifier on the IntPtr parameters rather than ref, as I had initially tried

                    That depends entirely on the function at hand; you typically need to provide an IntPtr or be ready to receive one (with "out" keyword). I don't recall any Win32 function that provides a handle that way, they typically use the return value (and return zero for error, then you would call GetLastError for details). Greetings

                    Luc Pattyn [Forum Guidelines] [My Articles]


                    this weeks tips: - make Visual display line numbers: Tools/Options/TextEditor/... - show exceptions with ToString() to see all information - before you ask a question here, search CodeProject, then Google


                    L Offline
                    L Offline
                    Leslie Sanford
                    wrote on last edited by
                    #9

                    Luc Pattyn wrote:

                    That depends entirely on the function at hand; you typically need to provide an IntPtr or be ready to receive one (with "out" keyword). I don't recall any Win32 function that provides a handle that way, they typically use the return value (and return zero for error, then you would call GetLastError for details).

                    Oh, I wasn't clear. The example I gave in my earlier post was with waveOutOpen; it opens a waveform output device. The native version takes an pointer to a WAVEOUT handle and returns a MMRESULT value indicating the status of the operation. If the operation was successful, the handle is filled with a valid handle to the device. This handle is later used with other waveOutXXX functions to interact with the device. So in this specific case, I needed an unitialized IntPtr to pass as the handle modified by the out keyword. After the wave device has been opened, other waveOutXXX functions that are called expect the handle to be initialized. Does this make sense?

                    L 1 Reply Last reply
                    0
                    • L Leslie Sanford

                      Luc Pattyn wrote:

                      That depends entirely on the function at hand; you typically need to provide an IntPtr or be ready to receive one (with "out" keyword). I don't recall any Win32 function that provides a handle that way, they typically use the return value (and return zero for error, then you would call GetLastError for details).

                      Oh, I wasn't clear. The example I gave in my earlier post was with waveOutOpen; it opens a waveform output device. The native version takes an pointer to a WAVEOUT handle and returns a MMRESULT value indicating the status of the operation. If the operation was successful, the handle is filled with a valid handle to the device. This handle is later used with other waveOutXXX functions to interact with the device. So in this specific case, I needed an unitialized IntPtr to pass as the handle modified by the out keyword. After the wave device has been opened, other waveOutXXX functions that are called expect the handle to be initialized. Does this make sense?

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

                      Leslie Sanford wrote:

                      Does this make sense?

                      Of course, it does. I was not familiar with waveOutOpen, but I looked it up now, and you are right, it does output a handle, hence "out someIntPtr" is the right way to go. The only comment I could make is you don't need the "=new IntPtr()" part of your handle declaration, a simple "IntPtr handle;" should suffice. :)

                      Luc Pattyn [Forum Guidelines] [My Articles]


                      this weeks tips: - make Visual display line numbers: Tools/Options/TextEditor/... - show exceptions with ToString() to see all information - before you ask a question here, search CodeProject, then Google


                      L 1 Reply Last reply
                      0
                      • L Luc Pattyn

                        Leslie Sanford wrote:

                        Does this make sense?

                        Of course, it does. I was not familiar with waveOutOpen, but I looked it up now, and you are right, it does output a handle, hence "out someIntPtr" is the right way to go. The only comment I could make is you don't need the "=new IntPtr()" part of your handle declaration, a simple "IntPtr handle;" should suffice. :)

                        Luc Pattyn [Forum Guidelines] [My Articles]


                        this weeks tips: - make Visual display line numbers: Tools/Options/TextEditor/... - show exceptions with ToString() to see all information - before you ask a question here, search CodeProject, then Google


                        L Offline
                        L Offline
                        Leslie Sanford
                        wrote on last edited by
                        #11

                        Thanks for your responses. I have to say that this has been a humbling day. Code that I had written a couple of years ago that I thought was fine has turned out not to be correct. I've had to go back through my code and correct this problem.

                        L 1 Reply Last reply
                        0
                        • L Leslie Sanford

                          Thanks for your responses. I have to say that this has been a humbling day. Code that I had written a couple of years ago that I thought was fine has turned out not to be correct. I've had to go back through my code and correct this problem.

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

                          First of all, you're welcome. Second, that is a common situation when the playing field changes. Things are working fine, they look good, compile without hassles, run great, so you think they might be correct; and then something changes, it may still work fine, but we got new information or new insights, and we feel we have to adapt the code, so we learn new ways to be even "more correct" about it. I have lots of experience in writing C code for different embedded systems, and I can tell you, if you use five different compilers, it is just impossible to write one page of code that all compilers will digest without giving a single warning. Things have improved, newer languages are more strict; having a single tool vendor (Microsoft) also helps. But then documentation, whatever they try, is not good enough. It is great at describing API functions, and less so for general principles, do's and don'ts, etc. And to make matters worse, you need more than is officially available (examples, suggestions, bug work-arounds, ...) but lots of things you find on Internet (including on CP) seem OK but are plain wrong, often the authors are satisfied they got something that works, but did not bother (enough) about correctness and general fitness. I did investigate the IntPtr stuff when I developed TrayIconBuster (see one of my CP articles); I was hoping it would run on XP, Vista and Win64 and had read some messages signaling pitfalls in Win64. Having only XP-32 available, I had to research a lot before I came up with "my theory", the one I presented earlier. And I must admit, I did not get most of it from Microsoft documentation, and I don't really have proof, having only XP to test on. In earlier code I did not even use IntPtr, I used uint instead (the IntPtr stuff did not seem to have any added value, just some coding overhead), but I too learned it the hard way, so a couple weeks ago I revisited all my P/Invoke stuff and fixed the pointers. Having my own classes (LP_user32, LP_kernel32, ...) holding the prototypes helped a lot in finding them all; so it was a matter of adapting the prototypes, then let the compiler discover the remaining problem spots. One thing I did not understand from day one I started with .NET is why the heck doesn't Microsoft do what www.pinvoke.net is trying to do, i.e. provide complete and accurate prototypes for ALL Win32 functionality; they did provide all the header files in older Visual C versions, and they must have the files internally. Having them f

                          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