DLL import problem for experts

F

Frank

Hello,

i have a problem with the data exchange between a managed C# application and
an unmanged C++ DLL. The C# app fills some values of a structure and calls
the C++ DLL. This DLL reads the filled data from the structure and fills the
results into the same structure. This code above works, but sometimes the
data array is empty, although the GetMemory function returns true. For
example: i read 250kByte (~1000 function calls) 5 - 15 times the data array
is empty.

The DLL works in some other non .NET applications perfectly. So i think the
error must be in the C# application.

My code:

Definition of the structure in C#:

[StructLayout(LayoutKind.Sequential)] public class MemoryObject {
public volatile uint Address;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] public volatile
byte[] Data;
public volatile byte Length;
}

DLL-Import:
[DllImport("bus.dll", EntryPoint="GetMemory"
,ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)] static
extern bool GetMemory(uint DeviceNr, [In,Out] MemoryObject Memory);


Function call:
public bool GetXMemory(uint DeviceNr, uint Address, byte Length, ref byte[]
Data) {
MemoryObject MemData = new MemoryObject();
bool RetVal;

MemData.Data = new byte[256];
MemData.Address = Address;
MemData.Length = Length;
RetVal = GetMemory(DeviceNr, MemData);
System.Array.Copy(MemData.Data, 0, Data, 0, Length);

return RetVal;
}
 
N

Nicholas Paldino [.NET/C# MVP]

Frank,

A few things. I would first change the MemoryObject from a class to a
Struct. I imagine that you declare it as a class so that you can pass a
null pointer to the function at times.

Instead, I would declare the method to take an IntPtr, and then perform
the marshaling of the structure to/from unmanaged memory on your own (it
only takes a call to the static PtrToStructure and StructureToPtr methods on
the Marshal class).

Also, could it possibly be something in the GetMemory function itself
which is causing the problem?

Hope this helps.
 
F

Frank

Hello Nicholas,

thanks for your answer.

In the meantime i found the bug!

The error was the return value bool. It always returns true. A Visual C++
V6.0 (Win32-API) bool type is NOT the same as an .NET bool type. I changed
my function return value to a byte type at everything works.

Frank



Nicholas Paldino said:
Frank,

A few things. I would first change the MemoryObject from a class to a
Struct. I imagine that you declare it as a class so that you can pass a
null pointer to the function at times.

Instead, I would declare the method to take an IntPtr, and then perform
the marshaling of the structure to/from unmanaged memory on your own (it
only takes a call to the static PtrToStructure and StructureToPtr methods on
the Marshal class).

Also, could it possibly be something in the GetMemory function itself
which is causing the problem?

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Frank said:
Hello,

i have a problem with the data exchange between a managed C# application and
an unmanged C++ DLL. The C# app fills some values of a structure and calls
the C++ DLL. This DLL reads the filled data from the structure and fills the
results into the same structure. This code above works, but sometimes the
data array is empty, although the GetMemory function returns true. For
example: i read 250kByte (~1000 function calls) 5 - 15 times the data array
is empty.

The DLL works in some other non .NET applications perfectly. So i think the
error must be in the C# application.

My code:

Definition of the structure in C#:

[StructLayout(LayoutKind.Sequential)] public class MemoryObject {
public volatile uint Address;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] public volatile
byte[] Data;
public volatile byte Length;
}

DLL-Import:
[DllImport("bus.dll", EntryPoint="GetMemory"
,ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)] static
extern bool GetMemory(uint DeviceNr, [In,Out] MemoryObject Memory);


Function call:
public bool GetXMemory(uint DeviceNr, uint Address, byte Length, ref byte[]
Data) {
MemoryObject MemData = new MemoryObject();
bool RetVal;

MemData.Data = new byte[256];
MemData.Address = Address;
MemData.Length = Length;
RetVal = GetMemory(DeviceNr, MemData);
System.Array.Copy(MemData.Data, 0, Data, 0, Length);

return RetVal;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top