|
Try this template:
public __gc class Hello : public System::IDisposable
{
public:
Hello(void)
{
}
virtual ~Hello(void)
{
Dispose(false);
}
void Dispose()
{
Dispose(true);
}
protected:
void Dispose(bool disposing)
{
if (disposing)
{
System::GC::SuppressFinalize(this);
}
}
};
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
This was what I have done. However, I can't call Dipose() on an object of the derived class because it is hidden-by-name. I guess this template is only implemantable in C#, so I simply renamed Dispose(bool) to InternalDispose(bool), which works fine for me.
Nevertheless thanks for your answer.
- Andre
|
|
|
|
|
The Dispose(Boolean) has nothing to do with .NET. The interface IDisposable only defines Dispose(), so you are doing anything wrong here.
The Dispose(Boolean) is defined as either private or protected, so external classes are not supposed to access it.
See the doc for IDisposable, there is an MC++ example given there to confirm your approach.
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Yes, I *do* know. And I don't want to access Dispose(bool), but Dispose(). I give you an example of what I mean:
<br />
public __gc class B : public IDisposable<br />
{<br />
public:<br />
virtual ~B() <br />
{ <br />
Dispose(false); <br />
}<br />
<br />
virtual void Dispose() <br />
{ <br />
Dispose(true); <br />
}<br />
<br />
protected:<br />
virtual void Dispose(bool arg)<br />
{<br />
<br />
}<br />
};<br />
<br />
public __gc class D : public B<br />
{<br />
protected:<br />
virtual void Dispose(bool arg)<br />
{<br />
<br />
B::Dispose(arg);<br />
}<br />
};<br />
<br />
int _tmain(void)<br />
{<br />
D * d = new D();<br />
d->Dispose();<br />
return 0;<br />
}<br />
This is implemented as suggested in MSDN, isn't it? However, it does not work.
d->Dispose() generates a C2660 saying that Dispose does not accept 0 parameters. This error is obviously caused by the fact that Dispose() is hidden-by-name.
I could use d->B::Dispose() but this looks ugly to me, so I renamed Dispose(bool) to InternalDispose(bool).
Hope I could explain what I meant.
- Andre
|
|
|
|
|
VizOne wrote:
Hope I could explain what I meant.
Yeah, but you are missing the point main here.
VizOne wrote:
I could use d->B::Dispose() but this looks ugly to me, so I renamed Dispose(bool) to InternalDispose(bool).
Add some output to the D::Dispose or D::InternalDispose to see if it is being called!
A better picture is cast the D pointer to IDisposable, it will compile, but similar to the above you end up calling B::Dispose, it is similar to your d->B::Dispose() syntax.
int _tmain(void)
{
D * d = new D();
__try_cast<IDisposable*>(d)->Dispose();
return 0;
}
The best way is to implement the same interface in D, since you will not get the expected result by renaming.
Also, you trying to convert the IDisposable::Dispose() to virtual, it will compile but will not act as virtual method.
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Paul Selormey wrote:
Also, you trying to convert the IDisposable::Dispose() to virtual, it will compile but will not act as virtual method
Well I am sure it *does* act as a virtual method. Excerpt from MSDN doc on managed c++:
"The following features are supported for __gc interfaces:
All methods of an interface are implicitly pure virtual. Neither the keyword virtual nor the suffix =0 is required on an interface method declaration, although both are allowed"
Here is a small test in which I have included everything I mentioned so far. It works perfectly for me:
<br />
public __gc class B : public IDisposable<br />
{<br />
public:<br />
virtual ~B() <br />
{ <br />
Console::WriteLine("B::~B()");<br />
InternalDispose(false); <br />
}<br />
<br />
virtual void Dispose() <br />
{ <br />
Console::WriteLine("B::Dispose()");<br />
InternalDispose(true); <br />
}<br />
<br />
protected:<br />
virtual void InternalDispose(bool arg)<br />
{<br />
Console::WriteLine("B::InternalDispose(bool)");<br />
<br />
}<br />
};<br />
<br />
public __gc class D : public B<br />
{<br />
public:<br />
void Dispose() <br />
{ <br />
Console::WriteLine("D::Dispose()"); <br />
B::Dispose();<br />
}<br />
protected:<br />
<br />
void InternalDispose(bool arg)<br />
{<br />
Console::WriteLine("D::InternalDispose(bool)");<br />
<br />
B::InternalDispose(arg);<br />
}<br />
};<br />
<br />
int _tmain(void)<br />
{<br />
B * b = new D();<br />
b->Dispose();
}<br />
The output is (as expected)
D::Dispose()
B::Dispose()
D::InternalDispose(bool)
B::InternalDispose(bool)
Of course, in my final version I will mark B::Dispose() as __sealed and throw away D::Dispose()
- Andre
|
|
|
|
|
Nothing new, just re-implementing IDisposable to create the impression of a virtual method (in which case you do not have to use the "Internal" attachment) - have fun.
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Hi,
I'm writing a wrapper class. So i have a DLL that contains too many C functions. Anyway, one function has void pointer for out parameter (2nd parameter) like following;
void Test(void* pIn, void* pOut);
Function is trying to fill pOut parameter with some info. The problem has started here. I want to convert void* value String or StringBuilder class. I can do it under unmanaged C/C++ such as following code;
char* cpTest = new char[100];
Test(.... , static_cast<void*>(cpTest));
Now, i want to do it under managed C++. Eventually, which way should i follow?
Thank for your response...
Orkun GEDiK
|
|
|
|
|
You can pass the character array. Use the native structure System::IntPtr for the Test() function parameter.
You can then write
Test(..., System::IntPtr((void*)cpTest);
You can use it for both the in and out.
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Thank you for your response. System has generated following error;
VoidPtr.cpp(19) : error C2440: 'type cast' : cannot convert from '__wchar_t __gc[]' to 'void *'
Can only convert a __gc array to or from Object * or Array *
VoidPtr.cpp(19) : error C2440: 'type cast' : cannot convert from '__wchar_t __gc[]' to 'void *'
Can only convert a __gc array to or from Object * or Array *
The source code at below;
#include "stdafx.h"
#using <mscorlib.dll>
#include <tchar.h>
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma unmanaged
// Assume this block inside of DLL
void Test(void* pIn, void* pOut)
{
char* pTest = static_cast<char*>(pIn);
pOut = static_cast<void*>("Internal\0");
}
#pragma managed
void WrapperTest(String* strIn, String* strOut)
{
Test(System::IntPtr((void*)strIn->ToCharArray()), System::IntPtr((void*)strOut->ToCharArray()));
}
int _tmain(void)
{
String* strTestA = new String("Hello");
String* strTestB = new String("");
WrapperTest(strTestA, strTestB);
return 0;
}
Thank you...
Orkun GEDiK
|
|
|
|
|
Now, I see the picture clearer. You do not need the WrapperTest function and the System::IntPtr I mentioned earlier.
Get the char* and pass it to the Test method:
const wchar_t __pin* psz = PtrToStringChars( pString )
The following is defined in vcclr.h header file included in VC.NET. This the same function used by the CString to convert the System::String to CString.
PtrToStringChars(String* pString)
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Very good and useful information for me. Thank you. I've changed my code to following form;
<br />
#include "stdafx.h"<br />
<br />
#using <mscorlib.dll><br />
#include <tchar.h><br />
#include <vcclr.h><br />
<br />
using namespace System;<br />
using namespace System::Runtime::InteropServices; <br />
<br />
#pragma unmanaged<br />
void Test(void* pIn, void* pOut)<br />
{<br />
char* pTest = static_cast<char*>(pIn);<br />
pOut = ("Internal\0");<br />
}<br />
<br />
#pragma managed<br />
int _tmain(void)<br />
{<br />
String* strTestA = new String("Hello");<br />
String* strTestB = new String("");<br />
wchar_t __pin* pTestA = PtrToStringChars(strTestA);<br />
wchar_t __pin* pTestB = PtrToStringChars(strTestB);<br />
Test(static_cast<void*>(pTestA), static_cast<void*>(pTestB));<br />
return 0;<br />
}<br />
Now, i can pass the pointer into DLL function, but i can't get any data from DLL (2nd parameter of Test function. So, pOut should be filled some data at inside of DLL). Thank you for your help...
Best Regards...
Orkun GEDiK
|
|
|
|
|
But pTestB is not a buffer to receive. Simply define a buffer and pass it in the out parameter. There is no need for the strTestB.
char szTestB[BufferSize] = {0};
should be sufficient.
In the Test() function, you can do something simply like this:
lstrcpy(pOut, "Internal");
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Ok. That means, i can't use managed type for pOut parameter. Ok, now i'm happy. Thank you for your response. Good answer. Thank you.
Best Regards,
Orkun.
Orkun GEDiK
|
|
|
|
|
Hello,
I've question about AppDomain. Can i set or get any data between the processes (such proxy) that executed by "ExecuteAssembly" function. If there's a way, please send the code example.
Thank you.
Orkun GEDiK
|
|
|
|
|
Hi!I have a problem working with Wav data files.I read a sample (short int) i do a cast into a double int to work with it. when i multiply or sum or divide for a constant and the results isn't entire the sound become saturated.The code seems like that:
[......]
fin.read((char*)&sample,sizeof(short));
double samdouble=sample;
samdouble=sample*0.5; // for example
sample=short(samdouble);
fout.write((char*)&sample,sizeof(short));
[.....]
I hope somebody can help me because i'm stopped in my project for that problem and i'm beginning to lose the expectancy
|
|
|
|
|
Hello All,
I compiled an MC++ codes and it includes some unmanaged classes.
The codes works alright in a local folder, but when I moved it to a network
folder (local network folder) I get the following IO exception:
-----------------------------------------------------------------------
An unhandled exception of type 'System.IO.FileLoadException' occurred in
WindowsApplication2.exe
Additional information: Unverifiable assembly 'GIS.View' failed policy check.
-----------------------------------------------------------------------
Is there no way to get MC++ assemblies to execute safely from a network folder?
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
I think that this has nothing to do specially with C++ and that
it happens also when trying to start a C#-programm from a network
share.
I think you can reconfigure your .NET-framwork with the utilities
which have been added to the star menu under Accessories, Management
(My XP is german, so these are guesses)
There you have to assign "FullTrust" to the network-share you want
to use.
Unfortunately I have not fully understood this stuff myself and find
it rather annoying.
|
|
|
|
|
Thanks for the information. I also got related article on the news group.
If the code isn't verifiable (if it contains unsafe code), it can cause
security issues. If the assembly is loaded without sufficient permissions
(such as when it is loaded from an untrusted location), then the code will
not be allowed to execute.
To solve this problem, you can adjust the security on the destination
machine. This can be done by caspol utility.
For more information, please check following article:
http://msdn.microsoft.com/library/en-us/dnforms/html/winforms11122002.asp
For additional information about creating verifiable code in MC++, you may
want to install .NET Framework SDK 1.1 Beta from:
http://msdn.microsoft.com/visualc/productinfo/visualc03/default.asp
The article titled "Producing Verifiable Components with Managed Extensions
for C++" in the SDK maybe helpful.
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Hi!
I want to code a wrapper for an existing c++-class.
The class has a function to define a callback and
when I set the callback I can give it some data
for me on the way: A void*. I can use it to
store stuff I need when I'm inside the callback.
This should be a common c++-concept and I think
the best thing for the managed proxy-class I'm
writing is a delegate, so that the C#-users who
call the function can give it a delegate which
is then called by the callback-proxy.
So I store the two delegates inside a class:
<br />
__delegate void CallBackNewFile(String* fname,int size);<br />
__delegate void CallBackBytes(int size);<br />
<br />
__gc class ExtractInfo<br />
{<br />
public:<br />
CallBackNewFile* newfile;<br />
CallBackBytes* bytes;<br />
};<br />
Now I want to give the callback-function
a void*:
<br />
static bool Extract(String* cabfile,String* DestDir,bool DontMakeFolders,<br />
CallBackNewFile* newfile,CallBackBytes* bytes)<br />
{<br />
CCabExtractor cab;<br />
if (!cab.Create())<br />
return false;<br />
ExtractInfo __pin * inf=new ExtractInfo();<br />
inf->newfile=newfile;<br />
inf->bytes=bytes;<br />
cab.SetCallback(&mycallback,inf);<br />
<br />
Please notice the "ExtractInfo __pin * inf=new ExtractInfo();". Is
that the right way of pinning?
Converting the gc-pointer into a void* seems to work!
BTW:
The SetCallback function has this declaration:
<br />
void SetCallback (CALLBACKFUNC pCallback, void * pv)<br />
And now comes the problem:
My callbackfunction wants to do something with the passend void* pointer:
<br />
static bool __stdcall mycallback (void * pv, const char * lpszPath, DWORD cb)<br />
{<br />
ExtractInfo* i=(ExtractInfo*)(pv);<br />
if (lpszPath==NULL)<br />
{<br />
if (i->bytes)<br />
i->bytes(cb);<br />
} else {<br />
if (i->newfile)<br />
i->newfile(lpszPath,cb);<br />
}<br />
return true;<br />
}<br />
The problem is the line "ExtractInfo* i=(ExtractInfo*)(pv);
I can't get this line right so that it compiles!
I tried several variants. I think it won't let me get
a __gc class out of a void* pointer.
BUT: That class HAS to be a __gc class, otherwise
the compiler complained about declaring delegates inside
it.
Can someone help me?
How do I transport a managed pointer/reference THROUGH
unmanaged code?
How can I cast a void* into a reference to a managed
object?
Many thanks in advance!!!
|
|
|
|
|
You can pass a delegate to the callback. Please many here do not response to anonymous poster - there is nothing to hide anyway!
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Paul Selormey wrote:
You can pass a delegate to the callback. Please many here do not response to anonymous poster - there is nothing to hide anyway!
Thanks
Okay, I'm registered now. Strange that it's possible to post without registration...
What do you mean with "I can pass a delegate to the callback"?
My guess is that I can pass a delegate directly to the SetCallBack function.
This is interessting and might be a way to go, but does anybody know about
converting a void* into a reference to a managed object?
How to push .NET-stuff through existing c++-functions and APIs??
Many thanks in advance!
|
|
|
|
|
If you wish to pass native pointer like void* around, use the System::IntPtr. It has the constructor for void*.
System::IntPtr intPtr((void*)pv);
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
i got a basic .cpp file i use too be able too just compile it but in .net studio the compile buttons greyed out
how do i over come this?
|
|
|
|
|
Create an empty project console project and add your file to the project and compile it.
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|