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. Threading using the ref statement? Wha Happen?

Threading using the ref statement? Wha Happen?

Scheduled Pinned Locked Moved C#
comdata-structuresquestion
13 Posts 2 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.
  • J jremignanti

    My COM object is not implemented as an STA. so if it's marshalling, what can I do? (I know there probably isn't a short answer) thanks.

    H Offline
    H Offline
    Heath Stewart
    wrote on last edited by
    #4

    Instead of importing the typelib automatically, you may have to define your own interface in .NET (that which reflects the class interface of your OCX), putting the appropriate marshaling attributes (MarshalAsAttribute). See that class (and the System.Runtime.InteropServices namespace for more details (and it'd be good to take a quick glance before proceding). Question, though. Are you trying to pass the first byte array element as a reference, or do you want to pass the entire array. The way you're doing it means that you're passing the address of the first element and this will definitely requiring marshaling. If you want to pass the whole array as a ref, use ref myByteArray as a parameter instead. .NET will take care of a lot of things for you, including stuff like this.

    -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

    J 1 Reply Last reply
    0
    • H Heath Stewart

      Instead of importing the typelib automatically, you may have to define your own interface in .NET (that which reflects the class interface of your OCX), putting the appropriate marshaling attributes (MarshalAsAttribute). See that class (and the System.Runtime.InteropServices namespace for more details (and it'd be good to take a quick glance before proceding). Question, though. Are you trying to pass the first byte array element as a reference, or do you want to pass the entire array. The way you're doing it means that you're passing the address of the first element and this will definitely requiring marshaling. If you want to pass the whole array as a ref, use ref myByteArray as a parameter instead. .NET will take care of a lot of things for you, including stuff like this.

      -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

      J Offline
      J Offline
      jremignanti
      wrote on last edited by
      #5

      I want to pass the entire array, but what data type will my COM object be expecting if I pass ref bytearray? right now, the prototype for my COM method is: STDMETHODIMP CUSB::WriteSPI(unsigned char* datain, int size) so, when C# gets a hold of that, it takes the pointer as a ref byte in other words, what is the C++/COM equivalent of a ref to an array?

      H 1 Reply Last reply
      0
      • J jremignanti

        I want to pass the entire array, but what data type will my COM object be expecting if I pass ref bytearray? right now, the prototype for my COM method is: STDMETHODIMP CUSB::WriteSPI(unsigned char* datain, int size) so, when C# gets a hold of that, it takes the pointer as a ref byte in other words, what is the C++/COM equivalent of a ref to an array?

        H Offline
        H Offline
        Heath Stewart
        wrote on last edited by
        #6

        First, an array is always a reference type. While some examples use ref with arrays, it's really only necessary for value types (int, long, byte, etc.) Passing a reference type results in the address passed to the native function. For your interface, though, you'd want to write your method to that functions like so:

        [Guid("...")]
        public interface IUSB
        {
        void WriteSPI(
        [MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)]byte[] array,
        int size);
        // ...
        }

        This will marshal the array as the address to the first element, which is what you're wanting to do.

        -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

        J 1 Reply Last reply
        0
        • H Heath Stewart

          First, an array is always a reference type. While some examples use ref with arrays, it's really only necessary for value types (int, long, byte, etc.) Passing a reference type results in the address passed to the native function. For your interface, though, you'd want to write your method to that functions like so:

          [Guid("...")]
          public interface IUSB
          {
          void WriteSPI(
          [MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)]byte[] array,
          int size);
          // ...
          }

          This will marshal the array as the address to the first element, which is what you're wanting to do.

          -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

          J Offline
          J Offline
          jremignanti
          wrote on last edited by
          #7

          I understand, but C# still sees the unsigned char* from my COM method as a ref byte so how can I get around that? sorry to keep bugging you.

          H 1 Reply Last reply
          0
          • J jremignanti

            I understand, but C# still sees the unsigned char* from my COM method as a ref byte so how can I get around that? sorry to keep bugging you.

            H Offline
            H Offline
            Heath Stewart
            wrote on last edited by
            #8

            Hmm, it's usually right...but not always the easiest to implement. It would make sense, since ref'ing the first element would return the address of the array, but as you can see...it's not working. :(( What I was referring to was actually defining the interface yourself and not using the interop assembly that's generated automatically. Especially for small typelibs or for typelibs which you only need a couple of things (like many do for mshtml's typelib), it's just easier defining the interface with the right attributes and method placements (for IUnknown interfaces, order of the methods is important; for IDispatch interfaces, using the DispIdAttribute with the correct ID is important). You can still instantiate the COM object through the interop, or derive a class from AxHost and override the necessary things, also implementing your interface, or using various methods in the Marshal class or Type class, and set the reference to a variable defined as your class interface. Access the methods from the interface (as in all COM you should, anyway). Still, though, that method signature should be right. When you say jibberish, what exactly do you mean?

            -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

            J 1 Reply Last reply
            0
            • H Heath Stewart

              Hmm, it's usually right...but not always the easiest to implement. It would make sense, since ref'ing the first element would return the address of the array, but as you can see...it's not working. :(( What I was referring to was actually defining the interface yourself and not using the interop assembly that's generated automatically. Especially for small typelibs or for typelibs which you only need a couple of things (like many do for mshtml's typelib), it's just easier defining the interface with the right attributes and method placements (for IUnknown interfaces, order of the methods is important; for IDispatch interfaces, using the DispIdAttribute with the correct ID is important). You can still instantiate the COM object through the interop, or derive a class from AxHost and override the necessary things, also implementing your interface, or using various methods in the Marshal class or Type class, and set the reference to a variable defined as your class interface. Access the methods from the interface (as in all COM you should, anyway). Still, though, that method signature should be right. When you say jibberish, what exactly do you mean?

              -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

              J Offline
              J Offline
              jremignanti
              wrote on last edited by
              #9

              When I said it was putting out garbage data, when I call WriteSPI(dataarray, size) I was looking at the output in bytes and I would get: 00 00 AA 00 size 00 ... so the size value was being sent in the part that was supposed to be the data, the first three bytes of data was always the same though, no matter what I sent. Are you saying that I can write a separate interface for my COM object in C#, that will override the one that was automatically generated when I compiled the C++ code for the COM object? If so, I didn't realize you can do that. If I specify the GUID as an attribute for the object, it will be able to find it? hmmmm...

              H 1 Reply Last reply
              0
              • J jremignanti

                When I said it was putting out garbage data, when I call WriteSPI(dataarray, size) I was looking at the output in bytes and I would get: 00 00 AA 00 size 00 ... so the size value was being sent in the part that was supposed to be the data, the first three bytes of data was always the same though, no matter what I sent. Are you saying that I can write a separate interface for my COM object in C#, that will override the one that was automatically generated when I compiled the C++ code for the COM object? If so, I didn't realize you can do that. If I specify the GUID as an attribute for the object, it will be able to find it? hmmmm...

                H Offline
                H Offline
                Heath Stewart
                wrote on last edited by
                #10

                This definitely sounds like a marshaling problem. Seems like data about the array is being sent when you want the array data since the bytes should be the same on both. You shoud read Advanced COM Interop in the MSDN Library. Basically, you're interface is just a way to access the class. In COM, you treat every object through it's interface by QI'ing (QueryInterface) for the interface that the class implements. In .NET this is acheived by merely casting. You can define the interface in your project regardless of what is in the interop assembly, yes. As long as the method signatures are marshalable and similar (proper number of params) and use the same return types (should all be void unless PreserveSignature is true, which then you use int to represent an HRESULT). Just instantiate your COM class and cast it to the interface you redefined (remember, use the same GUID for the interface in the GuidAttribute and keep all that stuff the same I said in the previous post) and you should have a valid reference to your object through that interface (again, it's like calling QI, which doesn't care about qualified names like .NET does). I'm not sure I'm explaining this as easily as possible, but read that section in MSDN (or perhaps start with the more basic stuff that comes before it). COM interop is powerful but is also is a beast to tame.

                -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

                J 1 Reply Last reply
                0
                • H Heath Stewart

                  This definitely sounds like a marshaling problem. Seems like data about the array is being sent when you want the array data since the bytes should be the same on both. You shoud read Advanced COM Interop in the MSDN Library. Basically, you're interface is just a way to access the class. In COM, you treat every object through it's interface by QI'ing (QueryInterface) for the interface that the class implements. In .NET this is acheived by merely casting. You can define the interface in your project regardless of what is in the interop assembly, yes. As long as the method signatures are marshalable and similar (proper number of params) and use the same return types (should all be void unless PreserveSignature is true, which then you use int to represent an HRESULT). Just instantiate your COM class and cast it to the interface you redefined (remember, use the same GUID for the interface in the GuidAttribute and keep all that stuff the same I said in the previous post) and you should have a valid reference to your object through that interface (again, it's like calling QI, which doesn't care about qualified names like .NET does). I'm not sure I'm explaining this as easily as possible, but read that section in MSDN (or perhaps start with the more basic stuff that comes before it). COM interop is powerful but is also is a beast to tame.

                  -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

                  J Offline
                  J Offline
                  jremignanti
                  wrote on last edited by
                  #11

                  okay, I get it... Thanks a lot for your help. just one last question, for my new interface, do I use the GUID from the COM interface or from the COM class itself? that's it, I swear. thanks again. Jesse

                  H 1 Reply Last reply
                  0
                  • J jremignanti

                    okay, I get it... Thanks a lot for your help. just one last question, for my new interface, do I use the GUID from the COM interface or from the COM class itself? that's it, I swear. thanks again. Jesse

                    H Offline
                    H Offline
                    Heath Stewart
                    wrote on last edited by
                    #12

                    The interface.

                    -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

                    J 1 Reply Last reply
                    0
                    • H Heath Stewart

                      The interface.

                      -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

                      J Offline
                      J Offline
                      jremignanti
                      wrote on last edited by
                      #13

                      arrrrrgggggghh... Using the interface works fine, except when it is in my new thread. damn.

                      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