Thanks a ton Alok !

On 5 February 2014 14:35, Alok Gandhi <[email protected]> wrote:

> Ok I was able to finally lay my hands on this one.
>
> Follwing is a complete solution for : Write from Python (string or a json
> dump string), read from C++ (on a UserDataBlob)
>
> First of all, when writing with python you cannot simply use blob.value =
> "my string" as this is not written as 32 Byte Array which C++ can
> recognise. So you have to convert your data into a 32 Byte Array and then
> write it. Here's how to do it
>
> -----------------------------------------------------
> ----- Python Code for writing the data to blob-------
> -----------------------------------------------------
> # python standard array module so that we can store C/ C ++ types
> import array
>
> *stringToStore  = "Hello World!, 1234 !@#$"*
>
> # We need to convert this string to unsigned byte array
> byteArray = array.array('B', stringToStore)
>
> # As we have to convert this from unsigned byte (8 bit) to unsigned
> integer (32 bit),
> # we need to add some null (0) bytes at the end so the total elements in
> this array
> # are a multiple of 4. We will also have to know how many null bytes we
> are adding
>
> nbNullBytes = 0
> # Padding the end of byteArray with null bytes
> while len(byteArray) % 4 != 0:
>     byteArray.append(0)
>     nbNullBytes += 1
>
> # Now we convert the array to unsigned integer array (32 bit)
> intArray = array.array('I', byteArray.tostring())
>
> # And we also add the number of null bytes added at end as the first
> element
> # of this array, why ?? becuase a C++ reader function blob.GetValue()
> # expects that
> intArray.insert(0, nbNullBytes)
>
>
> # Ok we are done, now we can conviniently set this data on the blob
>
> # Create a blob
> blob = Application.ActiveSceneRoot.AddProperty('UserDataBlob', False,
> 'data')
>
> # And add the data as 32 bit array
> blob.Array32 = intArray
>
> # That's it we are done
> # Note - If you want to read this from python, then do not use data =
> blob.Value
> # as it will not work, you will have to do exactly the inverse of what we
> did
> # above and read it into python.
>
> -------------------------- end of python
> code------------------------------------
>
>
> Now for C++ code,
>
> What you were doing initially was fine, the only trick is to
> cast in the proper way.
>
> Here is the relevant part for your C++ code
>
> -------------------------------------------------------
> ----------- C++ code to read the data------------------
> -------------------------------------------------------
>
> // I am copying the same code as was posted in the
> // first message on this thread with some modifications
>
> CStatus simplexCPP_Update( CRef& in_ctxt ){
>
> OperatorContext ctxt(in_ctxt);
> Application app;
>  Operator op(ctxt.GetSource());
>  UserDataBlob b = ctxt.GetInputValue(0,2,0);
>
> const unsigned char *x = NULL;
> unsigned int size = 0;
> b.GetValue(x, size);
>
> // Here is the proper and safe casting from const unsigned char* to const
> char* (as is needed by CString)
> const char* s_ = reinterpret_cast<char*>(const_cast<unsigned char*>(x));
>
> // Now we can easily construct a CString from this const char*
> CString data(s_);
>
>  // and log it
> app.LogMessage(L"Data Read from Blob: " +  data, siVerboseMsg);
>  return CStatus::OK;
> }
>
> ------------ end of C++
> code-----------------------------------------------------
>
> That's it! It should work fine. I have already tested it on my side.
>
> Here is a the expalanation of the casting
>
> We have to cast from const unsigned char* to const char*. For this we need
> the 'reinterpret_cast' operator.
> This operator than cast a pointer from derived type (usigned char*)to
> another unrelated derived type  (char*) .
> But this operator cannot work with const attribute, so first we have to
> remove the constness. To do
> this we have to use the 'const_cast'. I did all of this in one line of
> code as shown above.
>
> I hope this examples works for other people on the list as well.
>
>
> PS: There are some things to consider, in your use case scenario:
> 1. If possible do write the data from C++ (as suggested already in this
> post). This
> way you don't have to go through the python array module conversion.
>
> 2. In your case, since you are converting everything (int, float, string)
> to an ASCII string,
> what you will get in C++ is the same, a SI CString. You will then have to
> deserialize it
> into respective data types to use them in your operator. If you use a C++
> writer, then
> you can simply use a schema as a struct and not to worry about this
> conversions.
> An excellent example to reading and writing these is available in the docs:
>
> http://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=si_cpp/classXSI_1_1UserDataBlob.html,topicNumber=si_cpp_classXSI_1_1UserDataBlob_html
>
> 3. Also I don't see an output port in your operator's update() code.
> Something like,
> OutputPort outPort = ctxt.GetOutputPort();
>  outPort.PutValue(0); // just putting a zero value on out port
>
> This might also crash soft, but I guess you removed it while posting.
>
>
> Cheers !
>
>
>
>
>
> On Tue, Feb 4, 2014 at 5:17 PM, Jeremie Passerin <[email protected]>wrote:
>
>> Could definitely use an example,
>> thanks Alok.
>>
>> ;-)
>>
>>
>> On 4 February 2014 13:52, Alok Gandhi <[email protected]> wrote:
>>
>>> You could definitely write through python and read through CPP. You can
>>> also read binary / ascii file on disk from CPP using streams if you want.
>>>
>>> I think your problem lies in reading the value in context of a CPP
>>> operator. The way to access data from the input port is where you are
>>> having a glitch, at least that's what I think.
>>>
>>> I am not near a machine right now so I cannot provide you with a
>>> specific code. But I will do so later today or tomorrow in case somebody
>>> does not answer before that.
>>>
>>> Sent from my iPhone
>>>
>>> On Feb 4, 2014, at 14:29, Tyler Fox <[email protected]> wrote:
>>>
>>> HI there,
>>> I'm the Tyler that Jeremie was talking about in the original post.
>>>
>>> Writing the data generation in c++ is gonna be a really tough sell due
>>> to time/knowledge/expertise constraints on this end. It's been a LONG time
>>> since I've written any c++, and I'm doing some not easily portable stuff in
>>> the python code.
>>>
>>> Would a possible workaround be to write a custom command that reads a
>>> file on disk, builds my class structure using that data, and send that over
>>> to my custom operator?
>>>
>>> Which leads to the question, is an operator's userData saved with the
>>> file?
>>>
>>> ~T.Fox
>>>
>>>
>>>
>>>
>>>
>>> On Tue, Feb 4, 2014 at 10:31 AM, Matt Lind <[email protected]>wrote:
>>>
>>>> Write it in CPP.
>>>>
>>>>
>>>>
>>>> If your data requirements are small, you can use a userdatablob
>>>> template to store basic values to make them language agnostic (mostly).  A
>>>> template is essentially a customparamset applied to the object and flagged
>>>> to be read by a userdatablob.  Templates also exist for userdatamaps.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> Matt
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> *From:* [email protected] [mailto:
>>>> [email protected]] *On Behalf Of *Jeremie
>>>> Passerin
>>>> *Sent:* Tuesday, February 04, 2014 10:28 AM
>>>> *To:* softimage
>>>> *Subject:* Re: [C++] Reading UserDataBlob as JSON String
>>>>
>>>>
>>>>
>>>> Thanks for the inputs guys. This is where I am wrong assuming that
>>>> assuming I can write Cpp just like I write Python.
>>>>
>>>>
>>>>
>>>> So let me explain you the root of the problem so maybe someone has an
>>>> idea how to solve it with another way.
>>>>
>>>>
>>>>
>>>> We have a solver in Cpp (for optimization purpose). This solver needs
>>>> to be initialized with some values that only need to be computed once. We
>>>> did a prototype in Python and it works just fine. The init values is just a
>>>> bunch of list of strings, integers and floats. Nothing weird.
>>>>
>>>> Rather than rewriting this whole initial computation in Cpp, which
>>>> would take us a lot of time (and is using some external python libraries),
>>>> we though we could just do the init in Python store the result in a
>>>> datablob and read this from the Cpp solver.
>>>>
>>>>
>>>>
>>>> What would be the best way to ready array of strings, integers and
>>>> floats stored somewhere in the scene from a Cpp solver ?
>>>>
>>>>
>>>>
>>>> thanks for your help !
>>>>
>>>>
>>>>
>>>> Jeremie
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On 3 February 2014 18:25, Alok Gandhi <[email protected]>
>>>> wrote:
>>>>
>>>> I'd side with exactly what Matt and Oleg are saying, the data stored in
>>>> a user data blob through C++ is essentially binary. That might be the cause
>>>> of the issue. I wrote some plugin for userdatablob using c++ but I was
>>>> writing the data instead of reading it. You can probably do the inverse of
>>>> what I did.
>>>>
>>>>
>>>>
>>>> Here is the code from my plugin:
>>>>
>>>>
>>>> ----------------------------------------------------------------------------------------------------------
>>>>
>>>> struct DataForBlob
>>>>
>>>> {
>>>>
>>>> const char* blobVal;
>>>>
>>>> } ;
>>>>
>>>>
>>>>
>>>>  DataForBlob blobData; blobData.blobVal =
>>>> CString(L"MSVDATA").GetAsciiString(); UserDataBlob blob ;
>>>> agentModel.AddProperty( L"UserDataBlob", false, L"msvResource", blob);
>>>> blob.PutValue((unsigned char*)&blobData, sizeof(blobData)) ;
>>>> blob.SetLock(siLockLevelAll);
>>>>
>>>>
>>>>
>>>>
>>>> --------------------------------------------------------------------------------------------------------
>>>>
>>>>
>>>>
>>>> On Mon, Feb 3, 2014 at 9:15 PM, Oleg Bliznuk <[email protected]> wrote:
>>>>
>>>> casting from char* to CString* is unsafe as you dont know how CString
>>>> is implemented. It can be even not null-terminated ( and most likely this
>>>> is true as its responsible to hold both wide and non-wide characters )
>>>> inside and in such case the "LogMEssage" internally may call something like
>>>> "GetLength() {return m_Length;}" but physically there is only
>>>> null-terminated char buffer or whatever JSON stuff can holds. First check
>>>> if the "x" is not NULL after GetVall call and then try to create CString
>>>> stringObj ( x ) and log it.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>>
>>>>
>>>>
>>>
>>>
>>
>
>
> --
>

Reply via email to