No problem, you are welcome. Just let me know if this works for you.

On Fri, Feb 7, 2014 at 11:40 AM, Jeremie Passerin <gerem....@gmail.com>wrote:

> Thanks a ton Alok !
>
>
> On 5 February 2014 14:35, Alok Gandhi <alok.gandhi2...@gmail.com> 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 <gerem....@gmail.com>wrote:
>>
>>> Could definitely use an example,
>>> thanks Alok.
>>>
>>> ;-)
>>>
>>>
>>> On 4 February 2014 13:52, Alok Gandhi <alok.gandhi2...@gmail.com> 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 <tbtt...@gmail.com> 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 <ml...@carbinestudios.com>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:* softimage-boun...@listproc.autodesk.com [mailto:
>>>>> softimage-boun...@listproc.autodesk.com] *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 <alok.gandhi2...@gmail.com>
>>>>> 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 <gbo...@gmail.com> 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