Obscure marshalling/pinvoke problem with 1, 2, 4, and 8 bytes structures
- From: "whodges" <whodges@xxxxxxxxx>
- Date: 26 Mar 2006 23:07:29 -0800
Hey all:
I'm having *exactly* the same problem that Torbjørn Vik described in
two of his posts titled "PInvoke failure" and "Obscure marshalling
problems (NullReferenceException)" (found them on Google Groups). He
unfortunately didn't receive a reply, so now I'm trying. :)
Basically, the problem is that I'm calling an exported C++ DLL function
from a C# application (I've actually use SWIG to wrap the C++ classes
as C# ones, if you're curious). I'm marshalling structures containing
primitive types between C++ and C# via these DLL calls. Here's a
stripped down example of what I'm doing:
C++ Side
--------------------------
CPP.h:
struct TestStruct
{
public:
TestStruct( ) { x = 0; f = 0; }
TestStruct(int x0, float f0) { x = x0; f = f0; }
int x;
float f;
};
class ExportedClass
{
public:
static void SetTest(TestStruct t) { TestStruct test = t; }
static TestStruct GetTest() { return TestStruct(); }
}
ExportedClass.cxx:
// Here's there's some exported __stdcall DLL functions that call
ExportedClass::SetTest
// and ExportedClass::GetTest - i'm fairly certain these are set up
just fine.
C# Side
---------------------------
TestStruct.cs:
[StructLayout(LayoutKind.Sequential)]
public struct TestStruct
{
public int x;
public float f;
public TestStruct(int x0, float f0)
{
x = x0;
f = f0;
}
}
TestPINVOKE.cs:
// Here's there's some .NET DllImport statements that import the
function defined in
// ExportedClass.cxx. It only has the EntryPoint attribute.
ExportedClass.cs:
public class ExportedClass
{
public static TestStruct GetTest( ) { return TestPINVOKE.<exported
GetTest function>(); }
public static void SetTest(TestStruct t) { TestPINVOKE.<exported
SetTest function>(t); }
}
TestCode.cs:
ExportedClass.SetTest(new TestStruct(1, 2));
TestStruct t = ExportedClass.GetTest();
------------------------------
Ok, so, that's a messy nutshell of what I'm doing. Now, TestStruct in
my example is 8 bytes in size. For some reason, this causes the call
to ExportedClass.GetTest() to fail with an "unable to find entry point
named..." exception. The ExportedClass.SetTest works fine (checked
everything out). Now, GetTest *only* fails if TestStruct is 1, 2, 4,
or 8 bytes in size. It works perfectly for *any other structure
sizes*. If, for example, I were to insert an additional float into
TestStruct on both the C++ and C# side, GetTest would work fine since
the structure is now 12 bytes. It's baffling.
To add to the weirdness, if I remove TestStruct's constructors from the
C++ side, GetTest works fine. As a side note, both the C++ and C#
versions of TestStruct *must* be the same size in bytes for SetTest to
work. Otherwise it fails too. The makes sense though.
Now, I'm not at liberty to alter the C++ code, so I just can't go about
sticking a char or byte in to bump the struct to 9 bytes and avoid this
whole messed. I have a bunch of other 16 byte structures that I'm
marshalling back and forth between unmanaged and managed code with
absolutely no trouble. It uses exactly the same mechanism as I
described above.
If *anybody* out there has seen anything like this, or has some ideas,
please, I'm all ears. I've spent about 30 hours on this problem and
it's driving my nuts. I've played with a lot of the C++ linking and
code generation settings (structure alignment, __cdecl/__stdcall,
etc.), along with the Pack and Size attributes of StructLayout and the
CallingConventions attribute of DllImport. Suggestions?
.
- Follow-Ups:
- Re: Obscure marshalling/pinvoke problem with 1, 2, 4, and 8 bytes structures
- From: Mattias Sjögren
- Re: Obscure marshalling/pinvoke problem with 1, 2, 4, and 8 bytes structures
- From: Willy Denoyette [MVP]
- Re: Obscure marshalling/pinvoke problem with 1, 2, 4, and 8 bytes structures
- Prev by Date: RE: error '80070002' intermitent
- Next by Date: MC++ ... unable to compile my code correctly :-(
- Previous by thread: Re: Referencing a COM component in C++.NET
- Next by thread: Re: Obscure marshalling/pinvoke problem with 1, 2, 4, and 8 bytes structures
- Index(es):
Relevant Pages
|