469,350 Members | 1,830 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,350 developers. It's quick & easy.

Pointers btwn C# and C++

I have a native C++ pointer object which I need to hold in a C# environment,
initialize in the C++ environment and the pass between the C# and C++
environments. Which is the data structure to use? I have tried to use an
IntPtr in C#, send it through C++/CLI as a System::IntPtr and convert it to a
pointer of my class in the end, but that gives compilation errors. What I
guess I need is som C# equivalence to a void* to keep in the C# environment.
But I have no clue how to do it...
May 24 '07 #1
6 13050
>I have tried to use an
IntPtr in C#, send it through C++/CLI as a System::IntPtr and convert it to a
pointer of my class in the end, but that gives compilation errors.
Can you post the errors and your code? Using IntPtr should work
nicely. You can also use an actual void* in C# if you enable unsafe
code.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
May 24 '07 #2

"Joachim" <Jo*****@discussions.microsoft.comwrote in message
news:97**********************************@microsof t.com...
>I have a native C++ pointer object which I need to hold in a C#
environment,
initialize in the C++ environment and the pass between the C# and C++
environments. Which is the data structure to use? I have tried to use an
IntPtr in C#, send it through C++/CLI as a System::IntPtr and convert it
to a
pointer of my class in the end, but that gives compilation errors. What I
guess I need is som C# equivalence to a void* to keep in the C#
environment.
But I have no clue how to do it...
An IntPtr is the right thing to use, as long as this is a native pointer,
i.e. not a pointer into a garbage collected object. Use the ToPointer()
method to get the native pointer back.
May 24 '07 #3
The C# app:

IntPtr m_DVPSDK_ptr;

[DllImport(g_wrapper_dll_path)]
static extern int Initialize(
out IntPtr class_ptr,
ref int[] devices_ids,
Int32 encoder_id);

[DllImport(g_wrapper_dll_path)]
static extern string GetLastError(
IntPtr class_ptr,
Int32 encoder_id);

void Initialize()
{
int[] l_devs_ids = new int[g_max_devices];
int l_nr_of_devices = Initialize(
out m_DVPSDK_ptr,
ref l_devs_ids,
m_settings.EncoderId);

if (l_nr_of_devices == 0)
{
//TODO: throw error?
}
}
The C++/CLI code:

extern "C" int Initialize(
System::IntPtr class_ptr,
array<int>^ devices_ids,
int encoder_id)
{
return Impl::Initialize(
(DVP1412DLL*) class_ptr, //ERROR 2 BELOW
devices_ids,
encoder_id);
}

Error 2 error C2440: 'type cast' : cannot convert from 'System::IntPtr' to
'DVP1412DLL *'

extern "C" const System::String^ GetLastError(
System::IntPtr class_ptr,
int encoder_id)
{
return Impl::GetLastError(
(DVP1412DLL*) class_ptr, //ERROR 12 BELOW
encoder_id);
}
Error 12 error C2440: 'type cast' : cannot convert from 'System::IntPtr' to
'DVP1412DLL *'
"Mattias Sjögren" wrote:
>
I have tried to use an
IntPtr in C#, send it through C++/CLI as a System::IntPtr and convert it to a
pointer of my class in the end, but that gives compilation errors.

Can you post the errors and your code? Using IntPtr should work
nicely. You can also use an actual void* in C# if you enable unsafe
code.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
May 25 '07 #4
Only declaring an IntPtr (IntPtr myPtr;) in C# and passing it as an out
parameter to the C++ dll should work just fine then?

"Ben Voigt" wrote:
>
"Joachim" <Jo*****@discussions.microsoft.comwrote in message
news:97**********************************@microsof t.com...
I have a native C++ pointer object which I need to hold in a C#
environment,
initialize in the C++ environment and the pass between the C# and C++
environments. Which is the data structure to use? I have tried to use an
IntPtr in C#, send it through C++/CLI as a System::IntPtr and convert it
to a
pointer of my class in the end, but that gives compilation errors. What I
guess I need is som C# equivalence to a void* to keep in the C#
environment.
But I have no clue how to do it...

An IntPtr is the right thing to use, as long as this is a native pointer,
i.e. not a pointer into a garbage collected object. Use the ToPointer()
method to get the native pointer back.
May 25 '07 #5
Seemed like it had to do with that I declared the functions as

__declspec(dllexport)

However, even though it compiles, the value of the IntPtr is not changed in
C# even though it is in C++

"Joachim" wrote:
The C# app:

IntPtr m_DVPSDK_ptr;

[DllImport(g_wrapper_dll_path)]
static extern int Initialize(
out IntPtr class_ptr,
ref int[] devices_ids,
Int32 encoder_id);

[DllImport(g_wrapper_dll_path)]
static extern string GetLastError(
IntPtr class_ptr,
Int32 encoder_id);

void Initialize()
{
int[] l_devs_ids = new int[g_max_devices];
int l_nr_of_devices = Initialize(
out m_DVPSDK_ptr,
ref l_devs_ids,
m_settings.EncoderId);

if (l_nr_of_devices == 0)
{
//TODO: throw error?
}
}
The C++/CLI code:

extern "C" int Initialize(
System::IntPtr class_ptr,
array<int>^ devices_ids,
int encoder_id)
{
return Impl::Initialize(
(DVP1412DLL*) class_ptr, //ERROR 2 BELOW
devices_ids,
encoder_id);
}

Error 2 error C2440: 'type cast' : cannot convert from 'System::IntPtr' to
'DVP1412DLL *'

extern "C" const System::String^ GetLastError(
System::IntPtr class_ptr,
int encoder_id)
{
return Impl::GetLastError(
(DVP1412DLL*) class_ptr, //ERROR 12 BELOW
encoder_id);
}
Error 12 error C2440: 'type cast' : cannot convert from 'System::IntPtr' to
'DVP1412DLL *'
"Mattias Sjögren" wrote:
>I have tried to use an
>IntPtr in C#, send it through C++/CLI as a System::IntPtr and convert it to a
>pointer of my class in the end, but that gives compilation errors.
Can you post the errors and your code? Using IntPtr should work
nicely. You can also use an actual void* in C# if you enable unsafe
code.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
May 25 '07 #6

"Joachim" <Jo*****@discussions.microsoft.comwrote in message
news:D4**********************************@microsof t.com...
Seemed like it had to do with that I declared the functions as

__declspec(dllexport)

However, even though it compiles, the value of the IntPtr is not changed
in
C# even though it is in C++
a C# ref or out parameter must be declared in C++/CLI as a reference
parameter.
>
"Joachim" wrote:
>The C# app:

IntPtr m_DVPSDK_ptr;

[DllImport(g_wrapper_dll_path)]
static extern int Initialize(
out IntPtr class_ptr,
ref int[] devices_ids,
Int32 encoder_id);
Don't do this. To use C++/CLI functions from C#, add a reference to the
generated DLL.
>>
[DllImport(g_wrapper_dll_path)]
static extern string GetLastError(
IntPtr class_ptr,
Int32 encoder_id);

void Initialize()
{
int[] l_devs_ids = new int[g_max_devices];
int l_nr_of_devices = Initialize(
out m_DVPSDK_ptr,
ref l_devs_ids,
m_settings.EncoderId);

if (l_nr_of_devices == 0)
{
//TODO: throw error?
}
}
The C++/CLI code:

extern "C" int Initialize(
System::IntPtr class_ptr,
array<int>^ devices_ids,
int encoder_id)
{
return Impl::Initialize(
(DVP1412DLL*) class_ptr, //ERROR 2 BELOW
Should be class_ptr->ToPointer(), but see below...
>devices_ids,
encoder_id);
}
The compiler shouldn't even allow what you're doing... you have managed
types as parameters, and those are limited to member methods of managed
types. Create a ref class and make these functions static methods within
that class. Or, make them instance methods, so you don't have to pass
around class_ptr.

You're also missing a level of indirection all over the place here. You
want Impl::Initialize to fill in the pointer, right?

Then:

int Initialize( System::IntPtr% class_ptr, array<int>^ devices_ids, int
encoder_id)
{
DVP1412DLL objectPointer;
int retval = Impl::Initialize(&objectPointer, devices_ids, encoder_id);
class_ptr = gcnew System::IntPtr(objectPointer);
return retval;
}
>>
Error 2 error C2440: 'type cast' : cannot convert from 'System::IntPtr'
to
'DVP1412DLL *'

extern "C" const System::String^ GetLastError(
System::IntPtr class_ptr,
int encoder_id)
{
return Impl::GetLastError(
(DVP1412DLL*) class_ptr, //ERROR 12 BELOW
encoder_id);
}
Error 12 error C2440: 'type cast' : cannot convert from 'System::IntPtr'
to
'DVP1412DLL *'
"Mattias Sjögren" wrote:
>
I have tried to use an
IntPtr in C#, send it through C++/CLI as a System::IntPtr and convert
it to a
pointer of my class in the end, but that gives compilation errors.

Can you post the errors and your code? Using IntPtr should work
nicely. You can also use an actual void* in C# if you enable unsafe
code.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

May 25 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by iceColdFire | last post: by
27 posts views Thread by Susan Baker | last post: by
3 posts views Thread by ozbear | last post: by
9 posts views Thread by Mikhail Teterin | last post: by
12 posts views Thread by Lance | last post: by
92 posts views Thread by Jim Langston | last post: by
25 posts views Thread by J Caesar | last post: by
54 posts views Thread by Boris | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.