|
There is another way besides COM interop, but it's not easy and probably not recommended (being that most of the functions and structures are undocumented).
You can host the CLR yourself using the unmanaged functions of the .NET Framework. You create a default AppDomain that creates your application's AppDomain. From there, you can actually do some things with the managed DLL, but it is a difficult process. COM interop is definitely easier, I just wanted to provide another alternative.
For more information, look-up CorBindToCurrentRuntime and CorBindToRuntimeEx . This will give you the starting points for the rest.
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
|
I just jumped in to MC and am having some string problems.
I have 2 functions in c++ that I wanted to wrap with MC to use from c#. The def are as follows.
<br />
int EncryptString (wchar_t * pszString, wchar_t * & pszResultString);<br />
int DecryptString (wchar_t * pszString, wchar_t * & pszResultString);<br />
The first param of both is a string. the second is a string that acts as a buffer for the return value. How do I get these into MC?
I want to have a managed function that will take either 2 strings or a string and a StringBuilder.
<br />
void CAES::DecryptStr(String* DecString, StringBuilder* Buff)<br />
{<br />
<br />
}<br />
What do I need to put in the function to get DecString and Buff into something I can pass DecryptString? I need Buff to hold the output and return to c# intact etc.
TIA
|
|
|
|
|
Hello,
Check out System.Runtime.InteropServices.Marshal . Specifically: the StringTo... and PtrTo... methods.
Hope this helps,
Nathan
---------------------------
Hmmm... what's a signature?
|
|
|
|
|
Thanks for the reply. I have been working with that for a while now. I got the simple wchar_t to go easily. Do you know how to do the string builder buffer? I need it to copy to the wchar_t and then get whatever comes out back into the string builder.
Also do you know of any good reading on this subject? I have found lots of stuff, just nothing more advanced than a simple string to string conversion.
Thanks!
This is what I have so far in the decrypt sub.
<br />
wchar_t __nogc* pStr = static_cast<wchar_t*>(Marshal::StringToHGlobalUni(EncString).ToPointer()); <br />
wchar_t __nogc* pBuf = ;
int Ret;<br />
<br />
Ret = DecryptString(pStr,pBuf);<br />
|
|
|
|
|
To copy the StringBuilder into the pBuf, you should be able to exactly the same thing that you did with the first String.
<br />
String* pStringTemp = Buf->ToString();<br />
wchar_t __nogc* pBuf = static_cast(Marshal::StringToHGlobalUni(pStringTemp).ToPointer());<br />
Then to copy back into the StringBuilder just do:
Buff->Remove(0,Buf->Length);
Buff->Append(new String(pszResultString));
Hope this helps get you going again... (not tested
-Nathan
---------------------------
Hmmm... what's a signature?
|
|
|
|
|
Thanks a lot!! That got me there.
Boy MC is giving me a headache.
|
|
|
|
|
Glad that I could be of help. I forgot to answer your question about reading material. I don't have any good articles off the top of my head, but a good book on the subject is:
Programming with Managed Extensions for Microsoft Visual C++ .NET--Version 2003[^]
Just the first chapter alone is worth the money. The author should give me a little cash, I think I have posted that book 3 times now here... oh well... I like it a lot...
I like MC++ but it is kind of a pain... It allows a lot of cool things to happen.
Yea, legacy code support
---------------------------
Hmmm... what's a signature?
|
|
|
|
|
OK I'm about to throw MC out the window.
Here is my code
<br />
void CAES::EncryptStr(String* EncString, StringBuilder* Buff)<br />
{<br />
wchar_t __nogc* pStr = static_cast<wchar_t*>(Marshal::StringToHGlobalUni(EncString).ToPointer()); <br />
String* pStringTemp = "";<br />
wchar_t __nogc* pBuf = static_cast<wchar_t*>(Marshal::StringToHGlobalUni(pStringTemp).ToPointer());<br />
<br />
int Ret;<br />
<br />
Ret = EncryptString(pStr,pBuf);<br />
<br />
Buff->Remove(0,Buff->Length);
Buff->Append(new String(pBuf));
<br />
}<br />
This worked fine a few mins ago. NOTHING HAS CHANGED IN THE WHOLE PROJECT!!! Now I get an unhandled exception in mscorlib. It is a stack overflow exception. It happens on the Buff->Remove line. If I take it out it happens on the Buff->Append line.
The only think I did was make some functions in the non managed class I have private with the private: keywork in my header. After this it broke. I removed the private keyword and it's still broke.
Any ideas?
Further info: It happens when I call any framework thing after comming back from the dll also. I tried to show a messagebox and it failed also. This was after the call to EncryptString. I removed the Buff-> stuff so the method would return. It doesn, but I get the exception after it gets back now.
|
|
|
|
|
Shouldn't you have to pass a type to the static_cast method (operator)?
Like:
<br />
wchar_t __nogc* pStr = static_cast<wchar_t*>(Marshal::StringToHGlobalUni(EncString).ToPointer()); <br />
String* pStringTemp = "";<br />
wchar_t __nogc* pBuf = static_cast<wchar_t*>(Marshal::StringToHGlobalUni(pStringTemp).ToPointer());<br />
I have no idea if that is a problem that you are having... Also you said you changed header file stuff... Did you make sure to do a clean and rebuild?
[Edit] You don't really need to do the String* pStringTemp at all... all you are doing is allocating an empty string... So you only need to declare pBuf and pass it in by reference like you are doing... Also, did you make sure to new the pBuf inside of your EncrString function? else you will be writing to a zero length char buffer...[/Edit]
-Nathan
P.S. about the static cast stuff... you can probably ignore me, I found that you need to use the little code project buttons to make them show up...
---------------------------
Hmmm... what's a signature?
|
|
|
|
|
Yeah, I did a clean build. I restored the header file from backup. No luck.
Here is the kicker...
I ported another class to see if it was with all of them or just this one. It works fine. And guess what, the other one works fine now also... Go figure. I have no idea what went wrong. Maybe it will do it again??
Oh well. Thanks for all your help and info.
|
|
|
|
|
And yet once again it won't work. I added a 3rd class that doesn't work either. an exception about a null pointer from mscorlib.
|
|
|
|
|
hmmm... I guess I would probably need to see your code... But check my last post about the String* and empty string...
If you want to email me or something outside of here... we can try that...
-Nathan
---------------------------
Hmmm... what's a signature?
|
|
|
|
|
I eventually just made a wchar_t buffer of the right size and passed a pointer to it to the function. When it gets back it copies the buffer to the string like you had above. Works fine now.
Thanks again. I'm going to pick up that book you mentioned soon.
|
|
|
|
|
hi,
I need help regarding the storage of images into oracle
using vc++.net
Thanks in Advance
|
|
|
|
|
Hi,
I'm using VStudio .NET 2003 Enterprise Architect, and I've build a program to convert some files (I did this in managed C++). But I've got a problem:
I need to install my program on network HD (probably on a server), and my collegaes don't want to have to install the software on each of their computers. They just want to be able to run it, or my program. I can install it on the network, so they can just use the .exe.
I don't use register or config files, all the files needed for IO (some input and some output files) are already available on their pc's, and those fiels will be selected using a dialog.
Can you help me making sure nobody needs to install the software (except for me)?
Thank you in advance,
Boudewijn Ector
|
|
|
|
|
They have to add a CodeGroup to their security config files. Since the app is across the network, it has limit functionality since .NET runs in a secure, sandbox-like manner.
The easiest way is to have them click Start->Settings->Control Panel->Administrative Tools->Microsoft .NET Framework Configuration, drill-down to Runtime Security Policy->Machine->All_Code and add a new code group using a membership condition like Site, Url, or StrongName (for a signed DLL) and enter the coresponding information. Click Next and select FullTrust, then Finish. They could also change the LocalIntranet code group to have FullTrust permissions, but this isn't always recommended, especially if you can't trust all the managed code on the network. This also doesn't give you much granual control over code on the network, in case you want to limit what a certain application can do.
Sound too hard? You can also create an XML config file that is either pushed out to the other developers that contains this information or have them import it using a similar method from above.
Also keep in mind that managed assemblies don't really need to be installed. They just need to be copied. This is called XCOPY deployment (although other copy mechanisms like a shell copy work just as well). .NET assemblies do not need to be registered (unless they are exposed as COM objects through COM interop and CCWs) and only need to be installed into the GAC if you want your libraries available to everything that wants it (i.e., other applications).
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
My managed C++ project (a Windows Forms project) wishes to re-use an existing C++ MFC statically linked library.
Since the existing library is one of mine, I simply inserted the vcproj file into the solution.
When I try to link I get the error "LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)".
Any ideas?
|
|
|
|
|
Okay, now that I've gotten past my first hurdle I am facing a little more complex problem -- how can I map handles to managed objects? I have a callback entry point and would like to retrieve an existing instance of a managed class to deal with the callback, based on the handle that the function gets as a parameter. But I can't have a global map from handle to class *, because .NET forbids non-managed classes from storing pointers to managed classes; and managed classes can't have non-local linkage. What do I do? There's got to be some way of doing it -- picture going from your WndProc to a window object.
My desired sequence of events is: object is created by a managed client. Object then registers a callback with the API and gets back a handle. Callback enters, sees handle and passes it to a lookup function which retrieves the object. Object deals with callback and returns. etc.
Can I have a map from handle to class * as a static member of the managed class? Something tells me I cannot...
|
|
|
|
|
I have come up with a stop-gap solution but it is quite inelegant and defeats the purpose, somewhat, of managed classes. It is this:
__gc class MyClass
{
static MyClass *instances;
MyClass *next;
public:
MyClass(): next(instances) { instances = this; }
MyClass *Lookup(HANDLE h) { /*iterate thru linked list til you find it */ }
}
When the callback enters it can call MyClass::Lookup and then use the returned instance to deal with the callback. *But* MyClass instances will never be deleted (if my understanding of __gc is correct) -- I have to add a Shutdown() function to remove the instance from the list -- and call this function just before the last referance to the instance goes out of scope.
What I want is a way to declare non-__gc pointers to managed type objects -- then the destructor of a MyClass would be called when the last __gc reference to it went out of scope, and the destructor could then be responsible for cleaning up the instances list and deregistering the callback. But it seems like there is no way to do this.
Maybe what I should do, is make MyClass be non-managed but give it a managed wrapper class. Then I think I can do exactly what I want. I will give this a try and report back.
READIN writin and rhythmetic
|
|
|
|
|
Hi,
When i am trying to create a new form which is derived from some other form it is giving me design time problems. ie., When i am creating a new form , i can design the form according to my needs. but if i am making it derived from other form. at run time it is working fine. but i am unable to see the form at design time. so, please tell me how can i create a form which is derived from some other base form.
|
|
|
|
|
Visual Inheretance isn't currently supported by the VC++ Windows Forms designer. As you've discovered the code compiles/runs fine, but the designer itself won't support this.
Nick Hodapp
This posting is provided “AS IS” with no warranties, and confers no rights. You assume all risk for your use. © 2003 Microsoft Corporation. All rights reserved.
|
|
|
|
|
I'm pretty new to managed C++ -- hopefully this is something easy to do. I want to call windows API functions from within the module where my managed class is defined. But when I write #include <windows.h>, I get this compiler error: "assembly access specifier modified from 'public'", on the line ine ServProv.h where IServiceProvider is declared, followed by a few more errors and then a compilation aborted. What should I be including instead of <windows.h>?
Thanks!
|
|
|
|
|
I have to define WIN32_LEAN_AND_MEAN before including windows headers. Thanks for your time anyways!
|
|
|
|
|