passing string to custom objects through a managed wrapper

passing string to custom objects through a managed wrapper

Anonymous
Not applicable
1,630 Views
13 Replies
Message 1 of 14

passing string to custom objects through a managed wrapper

Anonymous
Not applicable

I'm working on a mixed code project - Custom DBX objects wrapped and used in vb.net, ala polysamp or even simplesquare examples.

 

I've got most things going good - lot of work but still, it's going. oddly one of the harder things to do is pass string data into the wrapper due to the curse of unicode.  I'm sure there is a way to do this (i've seen the StringToWchar and WcharToString functions but failed to get use out of them).

 

Anyhow anyone got advice on this? I'll put all the (relavent) code below:

 

The variable in the custom object class:

 

const wchar_t* m_Suburb;

 

the get / set declarations in the class:

 

std::string getSuburb();
Acad::ErrorStatus setSuburb(std::string Suburb);

 

and [my attempts at] the definitions for them:

 

std::string SectionObject::getSuburb()
{

std::wstring ws;
ws = m_Suburb;
std::string str(ws.begin(),ws.end());
return str;
}

 

Acad::ErrorStatus SectionObject::setSuburb(std::string Suburb )
{
std::wstring widestr = std::wstring(Suburb.begin(), Suburb.end());

const wchar_t* widecstr = widestr.c_str();
m_Suburb=widecstr;
return Acad::eOk;
}

 

and the declaration for the wrapper of the property:

 

property std::string Suburb
{
std::string get ();
void set(std::string suburb);
}

 

...the definition of the wrapper:

 

std::string BCHF::SectionObjectWrap::mgSectionObject::Suburb::get()
{
return (GetImpObj()->getSuburb());
}

 

void BCHF::SectionObjectWrap::mgSectionObject::Suburb::set(std::string value)
{
Autodesk::AutoCAD::Runtime::Interop::Check(GetImpObj()->setSuburb(value));
}

 

 

 

and the only other relavent thing is the initialization in the constructor:

 

SectionObject::SectionObject () : m_SectNumber(1)
, m_Suburb(_T("s"))//<- here is the init for string - this i'm really making up, no idea how to initialize a wchar....
, m_ShowSectNumber(false)
, m_ShowArea(false)
, m_TxtMspace(0,0,0)
, m_TxtSizeMspace(0.0)
, m_Normal(0,0,1)
, m_pManaged(NULL) {
}

 

anyone else been here? I can't find much discussion about this, so any ideas appreciated 🙂

oh, and is there anyone to disable these smiley faces in code snippets?!?!? lol.

 

0 Likes
Accepted solutions (1)
1,631 Views
13 Replies
Replies (13)
Message 2 of 14

Anonymous
Not applicable

ok...thanks to Balaji I've got a start - PolySamp has it burried in there 🙂

 

now.... When I try to USE the polysamp example, it gives me grief. Largely (I suspect) because I modeled after SimpleSquare originally.

 

I'm being told this notation:

 

__property void set_Name(String* value);
__property String* get_Name();

 

is illegal in visual studio - and when I try to adapt polysamp to :

 

property String* Suburb

{
String* get ();
void set( String* suburb);
}

 

I get a bunch of:

"an ordinary pointer to a c++/cli reference is not aloud"

 

Wah. I was so close.

 

I'm also getting a lot of errors on StringToCIF and CIFToString - 

but one thing at a time....

 

i noticed that the declarations have a "ref" in simple square class and a "__gc" in Polysamp - maybe this is the diffence, no idea.

I had the whole thing working with the old notation - I'm looking at re-writing the whole thing to pass a string?!? there has to be an eaiser way :S

 

0 Likes
Message 3 of 14

Balaji_Ram
Alumni
Alumni

Hi Carl,

 

The Polysamp SDK sample uses the old CLR syntax. 

 

You can find the changes to migrate it to the new clr syntax here :

http://msdn.microsoft.com/en-us/library/b23b94s7(v=vs.90).aspx

 

From that article, you can find that the String* is to be replace with String^

I have attached the SimpleSquare sample with the changes to pass a String.

 

I have only verified that it builds ok. I haven't tested it, so please do let me know if there is a problem and if does not work.

 

Regards,

Balaji



Balaji
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 4 of 14

Anonymous
Not applicable

Thanks AGAIN for the push.

 

I'm not even kinda kidding, there are tears in my eyes right now;

 

my co-workers couldn't take anymore swearing either 😉

0 Likes
Message 5 of 14

Balaji_Ram
Alumni
Alumni

Sorry for the trouble. I am glad you have a sample to work on.

 

Both the samples, SimpleSquare and PolySamp are examples which were originally implemented using the Old CLR syntax. I migrated the SimpleSquare to use the new CLR syntax and post it in the ADN Devblog. But the Polysamp is not yet migrated and continues to use the old CLR syntax. So this can cause some trouble when portions from the managed wrapper of Polysamp are used. 

 

The MSDN link that I posted earlier should be a helpful reference in case you need to migrate such code in future.

 

Regards,

Balaji

 

 

 

 

 

 

 

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 6 of 14

Anonymous
Not applicable
Accepted solution

"Sorry for the trouble. I am glad you have a sample to work on."

 

lol very very true. while uh...a bit...out of date, without the samples these projects would simply be impossible. A collegue of mine and I were actually joking the other day about what these projects would be like without internet access...But I digress.

 

While I'm absolutely giving Balaji 100% credit for this save/solution, I'm going to post the final working syntax [that compiled for me. I haven't tested it much yet] here and flag it as the solution to help any other weary travellers in the future.

 

So here it is:

 

//the string internal variable declaration in your custom class:

TCHAR*  myPassedString;

 

//the get / set function declarations in your custom class:

const TCHAR* getMyPassedString() const;
Acad::ErrorStatus setMyPassedString(const TCHAR* myPassedString);

 

//the get / set function definitions in your custom class:

 

 

const TCHAR* myCustomClass::getMyPassedString() const
{
assertReadEnabled();
return myPassedString;
}

 

Acad::ErrorStatus myCustomClass::setMyPassedString(const TCHAR* value)
{
assertWriteEnabled();

acutDelString(myPassedString);
myPassedString= NULL;

if(value!= NULL)
{
acutUpdString(value, myPassedString);
}

return Acad::eOk;
}

 

 

/*HERE IS THE TRICKY BIT!!!! The Declaration for the Wrapper for the Custom Object

//>>>>pay attention to the new property notation, and that ^ has replaced the spots you would expect a *. <<<<<

//in a way it was staring me in the face from:

//    void add (SectionModifiedHandler^);

// but things like this in the wrapper:

//    inline SectionObject*  GetImpObj()

// do seem inconsistent...also the .NetWrapper Wizard uses the depreciated, and in VS2012, killed __property notation.

// it won't work in 2012 but seems to be working in 2010 in the sample - 2012 never even liked opening PolySamp at all -

// probably due to the removal of free "installers" from the Visual Studio suite.*/

 

property String^ MyPassedString

{
String^ get();
void set(String^ value);
}

 

//the definition for the Wrapper:

//get

String^ ADSY::ClassWrapNamespace::myCustomClass::MyPassedString::get()
{
return CIFToString(GetImpObj()->getMyPassedString());
}

//set

void ADSY::ClassWrapNamespace::myCustomClass::MyPassedString::set(String^ value)

{
Autodesk::AutoCAD::Runtime::Interop::Check(GetImpObj()->setMyPassedString(StringToCIF(value)));
}

 

 

 

__________________________________________________________________________________________________________

I've just included the relavent things to passing strings, and the class/variable names I've changed to make everything more clear... 🙂 hope that helps someone.

 

 

0 Likes
Message 7 of 14

owenwengerd
Advisor
Advisor

You don't need acutDelString() or the other gymnastics. The acedUpdString() function already does that for you.

--
Owen Wengerd
ManuSoft
0 Likes
Message 8 of 14

Anonymous
Not applicable

I'm happy to ammend it... a lot of what I'm reading seems outdated, but just to clarify, from the dev handbook begining, tips and techniques (and the sample itself):

 

Freeing Strings Returned as Non-const Pointers

When calling methods that return non-const string pointers (for example, AcDbSymbolTable::getName(char&* pName)), you should free the memory occupied by the returned string. For example:

 

// The getName() call should be followed by a call to
acutDelString(pLtName);pLtTableRcd->getName(pLtName);
// ... other code
acutDelString(pLtName);

 

so is that wrong now or just fluff...?

0 Likes
Message 9 of 14

Balaji_Ram
Alumni
Alumni

Hi Carl,

 

There is also an overload that uses AcString which is more convenient to use.

There is no need to cleanup if you create an AcString instance on the stack.

 

Regards,

Balaji



Balaji
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 10 of 14

Anonymous
Not applicable
AcString versions are indeed somewhat more convenient but beware that there is a bug in AcString version of AcDbBlockTableRecord::getName (see http://forums.autodesk.com/t5/Autodesk-ObjectARX/AcDbBlockTableRecord-getName-two-signatures-differe...

My two cents
0 Likes
Message 11 of 14

owenwengerd
Advisor
Advisor

@Anonymous wrote:

so is that wrong now or just fluff...?


I don't see any problem with that sample code; my comment applies only to your code.

--
Owen Wengerd
ManuSoft
0 Likes
Message 12 of 14

Anonymous
Not applicable

I'm getting a bad url link there?

0 Likes
Message 13 of 14

Anonymous
Not applicable
0 Likes
Message 14 of 14

Anonymous
Not applicable

🙂 Thanks!

 

Actually your doing me the favor, so no apology needed.

 

 

0 Likes