<m.p.dn.languages.vc>.]
I created the following DLL in managed C++:
-------- export.cpp -----------
/// cl /clr /LD export.cpp /link /NOENTRY nochkclr.obj
#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
[StructLayout(LayoutKind::Sequential)]
public __gc class T
{
private:
int x;
GCHandle gch;
public:
T(int x)
{
Console::WriteLine("### T.<ctor>({0})",__box(x));
this->x = x;
this->gch = GCHandle::Alloc(this,GCHandleType::Pinned);
}
~T(void)
{
gch.Free();
}
int get_x(void)
{
Console::WriteLine("### T.get_x() >>> {0}",__box(x));
return x;
}
void put_x(int x)
{
Console::WriteLine("### T.put_x({0})",__box(x));
this->x = x;
}
String* ToString(void)
{
return String::Format(
"${0:X8}",
__box(gch.AddrOfPinnedObject().ToInt32()));
}
};
extern "C" __declspec(dllexport) T* newT(int x)
{
T* obj = new T(x);
Console::WriteLine("*** newT({0}) >>> {1}",__box(x),obj);
return obj;
}
extern "C" __declspec(dllexport) void deleteT(T* obj)
{
Console::WriteLine("*** deleteT({0})",obj);
delete obj;
}
extern "C" __declspec(dllexport) int GetX(T* obj)
{
Console::WriteLine("*** GetX({0})",obj);
return obj->get_x();
}
extern "C" __declspec(dllexport) void SetX(T* obj, int x)
{
Console::WriteLine("*** SetX({0},{1})",obj,__box(x));
obj->put_x(x);
}
-------------------------------
And the following test application in unmanaged C++:
--------- test.cpp ------------
/// cl /EHsc test.cpp
#include <iostream>
using namespace std;
#pragma comment(lib,"export.lib")
class T;
extern "C" __declspec(dllimport) T* newT(int x);
extern "C" __declspec(dllimport) int GetX(T* obj);
extern "C" __declspec(dllimport) void SetX(T* obj, int x);
int main(int argc, char* argv[])
{
T* obj = newT(9);
cout << ">>> newT() >>> " << obj << endl;
cout << ">>> GetX() >>> " << GetX(obj) << endl;
SetX(obj,13);
cout << ">>> GetX() >>> " << GetX(obj) << endl;
}
-------------------------------
Both files are compiled as stated in each one's first
comment line (I am using the VC++ 7.1 compiler in VS.NET2003
from the command line).
This is the output:
-------------------------------
### T.<ctor>(9)
*** newT(9) >>> $00AA29D4
newT() >>> 00167CA0 *** GetX($00AA29D4)
### T.get_x() >>> 9 GetX() >>> 9 *** SetX($00AA29D4,13)
### T.put_x(13)
*** GetX($00AA29D4)
### T.get_x() >>> 9 GetX() >>> 9 -------------------------------
(
### lines are printed by the managed class,
*** lines are printed by the managed exports, lines are printed by the unmanaged code,
)
I would expect the value of T::x to be 13 when the second
GetX() is called, istead it still is 9, as if the this->x =
x; assignement in T::put_x() had no effect. I tried with and
without GCHandle and both GCHandleType::Pinned and
GCHandleType::Normal. In the case of GCHandleType::Pinned, I
print the object address and it is always the same, so the
call is being made on the correct object.
However, the assignement is still ineffective, as if the
object were marshalled by value and thus only the copy were
used.
What am I missing here to make it work as I expected?
TIA
--
// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net