Convert (managed) FILETIME to (unmanaged) FILETIME

  • Thread starter Thread starter rob.zumwalt
  • Start date Start date
R

rob.zumwalt

Hi All,

I have written a wrapper around a C++ class to make it available to C#,
built into a dll. This has gone just fine, but one of the methods in
the C++ class takes a FILETIME pointer as an argument (from windows.h).
For example:

timer.h (C++)
------------
#include "windows.h"

public __gc class foo
{
public:
static void getTime( FILETIME * );
}


However, the problem is when I try to call this from C# (in an unsafe
method). My call to it looks like:

needsTime.cs (C# .NET 2.0)
---------------------
using System.Runtime.InteropServices.ComTypes;

<snip />

FILETIME myTime = new FILETIME();

foo.getTime( &myTime );


Building this produces the following error, which I cannot seem to
resolve:

Argument '1': Cannot convert from
'System.Runtime.InteropServices.ComTypes.FILETIME*' to '_FILETIME*'

Any thoughts?

Thanks in advance!

-Rob
 
timer.h (C++)
------------
#include "windows.h"

public __gc class foo
{
public:
static void getTime( FILETIME * );
}


However, the problem is when I try to call this from C# (in an unsafe
method). My call to it looks like:


If you write the wrapper, why not change it to a type more friendly to
managed code? Something like

void getTime(System::Runtime::InteropServices::FILETIME __gc * );


Mattias
 
If you write the wrapper, why not change it to a type more friendly to
managed code? Something like

void getTime(System::Runtime::InteropServices::FILETIME __gc * );

Hi Mattias,

That simply moves my dilemna inside the wrapper, which _is_
preferrable, but ultimately I still have to convert from
System::Runtime::InteropServices::FILETIME * to _FILETIME*. (since the
function ultimately being called takes a _FILETIME pointer.)

I still get the same error, though now it is when building the C++ into
a dll.
 
Hi All,

I have written a wrapper around a C++ class to make it available to C#,
built into a dll. This has gone just fine, but one of the methods in
the C++ class takes a FILETIME pointer as an argument (from windows.h).
For example:

timer.h (C++)
------------
#include "windows.h"

public __gc class foo
{
public:
static void getTime( FILETIME * );
}


However, the problem is when I try to call this from C# (in an unsafe
method). My call to it looks like:

needsTime.cs (C# .NET 2.0)
---------------------
using System.Runtime.InteropServices.ComTypes;

<snip />

FILETIME myTime = new FILETIME();

foo.getTime( &myTime );


Building this produces the following error, which I cannot seem to
resolve:

Argument '1': Cannot convert from
'System.Runtime.InteropServices.ComTypes.FILETIME*' to '_FILETIME*'

Any thoughts?

Thanks in advance!

-Rob



You can't do this without marshaling, Windows.h FILETIME is an unmanaged struct, so the
method is expecting a native struct pointer, you are passing a pointer to a managed type
(value type).
Now, you have to options:
1 you "marshal" the System.Runtime.InteropServices.ComTypes.FILETIME to a long and pass this
as argument, or
2. you declare the C++ method argument in C++ as:
System.Runtime.InteropServices.ComTypes.FILETIME *
and marshall this one to a windows.h FILETIME

Note also that you should get rid of the old ME C++ syntax, use C++/CLI, and fully qualify
the System.Runtime.InteropServices.ComTypes.FILETIME if you don't want to get clashes with
the (deprecated) 'System.Runtime.InteropServices.FILETIME' in V2 of the framework.

Willy.
 
That simply moves my dilemna inside the wrapper, which _is_
preferrable, but ultimately I still have to convert from
System::Runtime::InteropServices::FILETIME * to _FILETIME*. (since the
function ultimately being called takes a _FILETIME pointer.)

Right, but it's usually easier to handle it on the C++ side with
type-unsafe casts and memcpys.

In this case, however, since FILETIME is such a trivial struct, I
would simply declare a temporary (Win32) FILETIME variable, fill that
with the values from the managed struct (member by member) and pass it
on to the native code.


Mattias
 
Thanks All,

I have solved it by just declaring a new variable in my wrapper method
of the unmanaged FILETYPE, then pass that to the function that needs
it. The function then populates the values for it, then I immediately
copy the values from the unmanaged FILETIME to the managed FILETIME,
whose address was passed in.

It's a solution ... well, lets call it a workaround.


Thanks again!

-Rob
 
Back
Top