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 / C++ / MFC
  4. CComSafeArray

CComSafeArray

Scheduled Pinned Locked Moved C / C++ / MFC
questioncomdata-structures
8 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.
  • P Offline
    P Offline
    pierre_ribery
    wrote on last edited by
    #1

    Hi! I have an activeX control, which should send variuous arrays to the client. What I have done, is to wrap these arrays into a CComSafeArray and then send it as a pointer to a VARIANT. How can I then on client side determine which datatypes the array consists of? Whether it is int, long, double, float and so on?

    J 1 Reply Last reply
    0
    • P pierre_ribery

      Hi! I have an activeX control, which should send variuous arrays to the client. What I have done, is to wrap these arrays into a CComSafeArray and then send it as a pointer to a VARIANT. How can I then on client side determine which datatypes the array consists of? Whether it is int, long, double, float and so on?

      J Offline
      J Offline
      JonEngle
      wrote on last edited by
      #2

      The variant type should tell you on the client (if your ActiveX control is putting them together correctly). For instance, the VT of the VARIANT would be VT_ARRAY | VT_I4 for longs, VT_ARRAY | VT_I2 for shorts, etc. It could be VT_ARRRAY | VT_VARIANT, which means that each element of the array is a variant itself, which agains means you'll have to test the VT.

      P 1 Reply Last reply
      0
      • J JonEngle

        The variant type should tell you on the client (if your ActiveX control is putting them together correctly). For instance, the VT of the VARIANT would be VT_ARRAY | VT_I4 for longs, VT_ARRAY | VT_I2 for shorts, etc. It could be VT_ARRRAY | VT_VARIANT, which means that each element of the array is a variant itself, which agains means you'll have to test the VT.

        P Offline
        P Offline
        pierre_ribery
        wrote on last edited by
        #3

        thanks for good answer! I have some other questions as well; 1) Will memcpy be a good approach to this task? If so, how will the code look then? My array consist of approx. 15000 elements. 2) How do I send an array of user defined structure elements?

        J 1 Reply Last reply
        0
        • P pierre_ribery

          thanks for good answer! I have some other questions as well; 1) Will memcpy be a good approach to this task? If so, how will the code look then? My array consist of approx. 15000 elements. 2) How do I send an array of user defined structure elements?

          J Offline
          J Offline
          JonEngle
          wrote on last edited by
          #4

          For question #1, maybe. It depends on how your data is stored. You can get a void * back from the safearray, then cast it to the type, the memcpy it: void *pData; SafeArrayAccessData(sa,&pData); memcpy((LPBYTE)pData,pMyByteArray,sizeof(BYTE)*numElements); or something similar. Question 2: This gets trickier. Different schools of thought: 1.) don't do that. Define the struct in IDL, define the interface to return those (say, maybe an Item property with an index). 2.) Someone has a gun to your head and says they'll kill you if you don't (only acceptable reason to do it this way): Create an array of variants. Each variant then in and of itself contains a safearray of bytes, which is one element in your array of structs. Version 2 of this, create a variant that is an array of bytes and memcpy the whole thing. If this is for something production, I highly suggest doing something different than blobbing it. It's much more extensible to have a collection interface that returns interfaces for each structure your defining: ActiveX Control | |----- property Item([in]long index, [out,retval] IStruct **ppIStruct) interface IStruct | |--- property name |--- property address etc etc, mapping a property value in IStruct to the value of your structure. If your using something like ATL, you might want to look at a tear-off interface for implementing this. Just a thought.

          P 1 Reply Last reply
          0
          • J JonEngle

            For question #1, maybe. It depends on how your data is stored. You can get a void * back from the safearray, then cast it to the type, the memcpy it: void *pData; SafeArrayAccessData(sa,&pData); memcpy((LPBYTE)pData,pMyByteArray,sizeof(BYTE)*numElements); or something similar. Question 2: This gets trickier. Different schools of thought: 1.) don't do that. Define the struct in IDL, define the interface to return those (say, maybe an Item property with an index). 2.) Someone has a gun to your head and says they'll kill you if you don't (only acceptable reason to do it this way): Create an array of variants. Each variant then in and of itself contains a safearray of bytes, which is one element in your array of structs. Version 2 of this, create a variant that is an array of bytes and memcpy the whole thing. If this is for something production, I highly suggest doing something different than blobbing it. It's much more extensible to have a collection interface that returns interfaces for each structure your defining: ActiveX Control | |----- property Item([in]long index, [out,retval] IStruct **ppIStruct) interface IStruct | |--- property name |--- property address etc etc, mapping a property value in IStruct to the value of your structure. If your using something like ATL, you might want to look at a tear-off interface for implementing this. Just a thought.

            P Offline
            P Offline
            pierre_ribery
            wrote on last edited by
            #5

            Thx! I am very happy by your answers! But I must admit that I dont follow you all the time! I am quite new to c++. Would you mind to give me a short example on the memcpy stuff? For instance how to do it with an array of doubles, and then send it to client? And regarding question 2, you say; "Each variant then in and of itself contains a safearray of bytes, which is one element in your array of structs." Why should it contain bytes and not doubles for instance? Last question; How would a code snipp for the idl look like? Lets say I have the following stucture: Code: typedef struct somePoints{ int a,b,c; } MY_STRUCT; I have the "somePoints" elements arranged in an array and have this get method; Code: MY_STRUCT *getArrayP(void) { return arrayP; } So by using CComSafeArray, how would you send this array? So far I have been iterating through the struct elements one by one, and then inserting a, b and then c. By doing is this way I feel that I put a lot of responsibility on the client, because he has to know that element i*3+0 is my a, i*3+1 is b and i*3+2 is c. Any way of improving this, at least making it easier for client? Cheers

            J 1 Reply Last reply
            0
            • P pierre_ribery

              Thx! I am very happy by your answers! But I must admit that I dont follow you all the time! I am quite new to c++. Would you mind to give me a short example on the memcpy stuff? For instance how to do it with an array of doubles, and then send it to client? And regarding question 2, you say; "Each variant then in and of itself contains a safearray of bytes, which is one element in your array of structs." Why should it contain bytes and not doubles for instance? Last question; How would a code snipp for the idl look like? Lets say I have the following stucture: Code: typedef struct somePoints{ int a,b,c; } MY_STRUCT; I have the "somePoints" elements arranged in an array and have this get method; Code: MY_STRUCT *getArrayP(void) { return arrayP; } So by using CComSafeArray, how would you send this array? So far I have been iterating through the struct elements one by one, and then inserting a, b and then c. By doing is this way I feel that I put a lot of responsibility on the client, because he has to know that element i*3+0 is my a, i*3+1 is b and i*3+2 is c. Any way of improving this, at least making it easier for client? Cheers

              J Offline
              J Offline
              JonEngle
              wrote on last edited by
              #6

              Well, it's extremely uncommon to have a structure with uniform data types. Most structs are more like struct { int value; float fvalue; short somethingElse; etc., etc. } Now, for your case, I'd do one of two approaches. The big question is do you have to support scripting environments? Option 1) Using the interface Define the structure in IDL. This looks pretty much identical to you C structure definition. Define a method that returns these: For instance, in your IDL struct MY_STRUCT{ long a; long b; long c; }; //as a method on your COM object [propget, id(1)] HRESULT Item([in[ Index,[out,retval] struct MyDataType* blah); And implement from there. Option 2) Using a big safearray Create a safearray of variants (one for each structure), then each variant is a safearray of VT_I4. It's up to your client to know what the order of each value means, which means that this approach is fairly brittle.

              P 2 Replies Last reply
              0
              • J JonEngle

                Well, it's extremely uncommon to have a structure with uniform data types. Most structs are more like struct { int value; float fvalue; short somethingElse; etc., etc. } Now, for your case, I'd do one of two approaches. The big question is do you have to support scripting environments? Option 1) Using the interface Define the structure in IDL. This looks pretty much identical to you C structure definition. Define a method that returns these: For instance, in your IDL struct MY_STRUCT{ long a; long b; long c; }; //as a method on your COM object [propget, id(1)] HRESULT Item([in[ Index,[out,retval] struct MyDataType* blah); And implement from there. Option 2) Using a big safearray Create a safearray of variants (one for each structure), then each variant is a safearray of VT_I4. It's up to your client to know what the order of each value means, which means that this approach is fairly brittle.

                P Offline
                P Offline
                pierre_ribery
                wrote on last edited by
                #7

                Thanks! This helped me a lot! Now this is hopefully my last post to this thread! Lets say I have the following code on client: CComVariant varArray; // Get the array from the server my_readCtrl.getArray(&varArray); // Decide the datatype of the Variant // Attach the safe array if(varArray.vt==VT_I1) { CComSafeArray saFromVariant; } else if(varArray.vt==VT_R8) { CComSafeArray saFromVariant; } saFromVariant.Attach (varArray.parray); This results in an compilation error since saFromVariant is not declared. That is obviously because the declarations are inside if statements. How to avoid this but still declared it correct? Thx

                1 Reply Last reply
                0
                • J JonEngle

                  Well, it's extremely uncommon to have a structure with uniform data types. Most structs are more like struct { int value; float fvalue; short somethingElse; etc., etc. } Now, for your case, I'd do one of two approaches. The big question is do you have to support scripting environments? Option 1) Using the interface Define the structure in IDL. This looks pretty much identical to you C structure definition. Define a method that returns these: For instance, in your IDL struct MY_STRUCT{ long a; long b; long c; }; //as a method on your COM object [propget, id(1)] HRESULT Item([in[ Index,[out,retval] struct MyDataType* blah); And implement from there. Option 2) Using a big safearray Create a safearray of variants (one for each structure), then each variant is a safearray of VT_I4. It's up to your client to know what the order of each value means, which means that this approach is fairly brittle.

                  P Offline
                  P Offline
                  pierre_ribery
                  wrote on last edited by
                  #8

                  I think I want to go for option 1 here. Can you show me how to write the code for the idl stuff? Thanks

                  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