I am trying to access a Double Dummy Solver dll (http://privat.bahnhof.se/wb758135/bridge/dll.html ) of unmanaged C++ code from a C# project, but I get the following error message:
An unhandled exception of type 'System.AccessViolationException'
occurred in Dds.Net.dll
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
The error seems to be around calling the method
Par which takes the three arguments
struct ddTableResults *tablep, struct parResults *presp, int vulnerable
Specifically, related to passing in the 2nd parameter which is described to be:
struct parResults
char parScore[2][16];
char parContractsString [2][128];
Here is my code:
My c# struct:
using System.Runtime.InteropServices;
namespace Dds.Net.Integration
{
[StructLayout(LayoutKind.Sequential)]
internal struct ParResults
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst =32)]
public char[,] parScore;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[,] parContractString;
}
}
dllimport to call the function :
[DllImport("dds.dll")]
public static extern int Par(DdTableResults tablep, int vulnerable, ParResults parResults);
Any idea of what I can do to get this working?
Many thanks!
as far as I understand, you c++ signature is
int Par(struct ddTableResults *tablep, struct parResults *presp, int vulnerable)
the c# one maybe is
[DllImport("dds.dll")]
public static extern int Par(ref DdTableResults tablep, ref ParResults parResults, int vulnerable);
c++ wants a poitner to DdTableResults and ParResults, without ref c# will pass structure by value.
Related
I am working in C# and I need to call a function in a C++ dll library. This function returns a struct but I can´t get anything.
This is the function I need to call and the struct that returns in C++ library:
ATHENA_API _DEVICE_INFO* __stdcall GetDeviceInfoKeepConnection(_DEVICE_INFO* pDeviceInfo);
typedef struct TD_DEVICE_INFO{
TCHAR chDeviceName[256];
int nCommPort;
int nECGPos;
int nNumberOfChannel;
int nESUType;
int nTymestampType;
int nDeviceHandle;
TCHAR chDeviceID[260];
}_DEVICE_INFO;
This is my C# code trying to call the function:
[DllImport(#"\BAlertSDK\ABM_Athena.dll")]
static extern _DEVICE_INFO GetDeviceInfoKeepConnection(_DEVICE_INFO deviceInfo);
[StructLayout(LayoutKind.Sequential)]
struct _DEVICE_INFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string chDeviceName;
public int nCommPort;
public int nECGPos;
public int nNumberOfChannel;
public int nESUType;
public int nTymestampType;
public int nDeviceHandle;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string chDeviceID;
}
void Test_Click()
{
_DEVICE_INFO d = new _DEVICE_INFO();
_DEVICE_INFO deviceInfo = GetDeviceInfoKeepConnection(d);
}
The only I can get is an empty _DEVICE_INFO object. I think my problem is that I am not defining correctly the DEVICE INFO struct.
I have never worked with dll´s to this level. Can you help me?
Thanks in advance.
Thanks to all!! The problem has solved with this:
Parameter pass by reference and struct charset Unicode.
It seems that the function GetDeviceInfoKeepConnection returns a pointer to _DEVICE_INFO struct. So, in your C# code, you need to change the definition of the function to:
[DllImport(#"\BAlertSDK\ABM_Athena.dll")]
static extern IntPtr GetDeviceInfoKeepConnection(IntPtr deviceInfo);
And then you can access the struct data like this:
void Test_Click()
{
_DEVICE_INFO d = new _DEVICE_INFO();
IntPtr pDeviceInfo = Marshal.AllocHGlobal(Marshal.SizeOf(d));
Marshal.StructureToPtr(d, pDeviceInfo, false);
IntPtr deviceInfo = GetDeviceInfoKeepConnection(pDeviceInfo);
_DEVICE_INFO result = (_DEVICE_INFO)Marshal.PtrToStructure(deviceInfo, typeof(_DEVICE_INFO));
Marshal.FreeHGlobal(pDeviceInfo);
}
Note that, to ensure that the memory is cleaned up after use, you should use the Marshal.FreeHGlobal method to free the memory that was allocated by Marshal.AllocHGlobal.
I'm trying to marshal a struct that is returned by my native code but I get System.Runtime.InteropServices.MarshalDirectiveException
It is not a output argument that already answered in other posts, it is return type.
C++ code:
typedef struct
{
bool success;
ErrorCode error_code;
char error_path[1025];
} Result;
DLLEXPORT Result GetResult();
ErrorCode is an enum,
C# equivalent:
[StructLayout(LayoutKind.Sequential)]
public struct Result
{
public byte success;
public ErrorCode error_code;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 1025)]
public char[] error_path;
}
[DllImport("shared", EntryPoint = "GetReult", CallingConvention = CallingConvention.Cdecl)]
public extern static Result GetResult();
I know the return stucts in C# p/invoke should be blitable type but I don't know if I can make my struct blittable using the Marshaling directives or not.
Is there any way do do that or is something other is wrong with my code?
If there is no way I need to change my API and make the return type as output argument.
Thanks.
You can make it blittable by using a fixed size buffer:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct Result
{
public byte success;
public ErrorCode error_code;
public fixed sbyte error_path[1025];
}
Note that I have used sbyte for the array element type. That's an 8 bit type that matches the unamanged char type which is also an 8 bit type. You used char in your C# which is a 16 bit type.
You may need to convert the fixed size buffer to a string, but exactly how to do that depends upon the encoding that you used. However, there are plenty of articles on that topic (converting fixed size buffer to string) that you can find by web search.
I have an unmanaged DLL that exports only a C style factory method that returns a new instance of a class (simplified here to look simple).
hello.h
#if defined(HWLIBRARY_EXPORT) // inside DLL
# define HWAPI __declspec(dllexport)
#else // outside DLL
# define HWAPI __declspec(dllimport)
#endif
struct HelloWorld{
public:
virtual void sayHello() = 0;
virtual void release() = 0;
};
extern "C" HWAPI HelloWorld* GetHW();
hello.cpp
#include "hello.h"
struct HelloWorldImpl : HelloWorld
{
void sayHello(){
int triv;
std::cout<<"Hello World!";
std::cin>>triv;
};
void release(){
this->HelloWorldImpl::~HelloWorldImpl();
};
HelloWorld* GetHW(){
HelloWorld* ptr = new HelloWorldImpl();
return ptr;
};
Now, I can use dllimport to access GetHW() but is there a way to access the member functions of the returned 'struct'... ie, sayHello and release?
I was also stuck with the same problem. This question was asked a while before. I commented to it for any better solution but didn't get any reply yet. So, reposting it.
When i googled, able to find out two solutions.
Solution1: Expose all the member functions in the C-style for the existing dll. Which i cant do, as it is a 3rd party dll.
Solution2: Write a managed C++ dll exposing the functionality of native C++ dll, which later can be used in your C# dll. Here many classes/functions are present. So, creating would take most of the time.
i got the above solutions from the link below.
How To Marshall
Please let me know if there is any better solution other than the above two solutions?
i have the source code for C++ solution. But what i though was not to touch C++ dll. If there is any possibility to do it in C#, it would be great.
If there is no alternative, i need to follow any one of the specified two solutions.
The C++ code is using the way abstract classes are implemented by the Visual C++ compiler. http://blogs.msdn.com/b/oldnewthing/archive/2004/02/05/68017.aspx. This memory layout is "fixed" because it is used for implementing COM interfaces. The first member of the struct in memory will be a pointer to a vtable containing the function pointers of your methods. So for a
struct HelloWorldImpl : public HelloWorld
{
public:
int value1;
int value2;
}
the "real" layout in memory would be:
struct HelloWorldImpl
{
HelloWorldVtbl *vtbl;
int value1;
int value2;
}
where vtbl would be:
struct HelloWorldVtbl
{
void *sayHello;
void *release;
}
Just for the sake of doing a complete response, I'm writing the example for this signatures:
struct HelloWorld {
public:
virtual int sayHello(int v1, int v2, int v3) = 0;
virtual void release() = 0;
};
C# code:
[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GetHW();
[StructLayout(LayoutKind.Sequential)]
struct HelloWorldVtbl
{
public IntPtr sayHello;
public IntPtr release;
}
Your functions are void Func(void) or int Func(int, int, int), but in truth they have a hidden parameter, this, so you can write them as:
int sayHello(HelloWorld*, int, int, int);
void release(HelloWorld*);
so in C# the delegate is
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate int Int32MethodInt32Int32Int32(IntPtr ptr, int v1, int v2, int v3);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void VoidMethodVoid(IntPtr ptr);
Then you can use
IntPtr ptr = GetHW();
IntPtr vtbl = Marshal.ReadIntPtr(ptr, 0);
HelloWorldVtblhw = (HelloWorldVtbl)Marshal.PtrToStructure(vtbl, typeof(HelloWorldVtbl));
Int32MethodInt32Int32Int32 sayHello = (Int32MethodInt32Int32Int32)Marshal.GetDelegateForFunctionPointer(hw.sayHello, typeof(Int32MethodInt32Int32Int32));
int res = sayHello(ptr, 1, 2, 3);
Console.WriteLine(res);
VoidMethodVoid release = (VoidMethodVoid)Marshal.GetDelegateForFunctionPointer(hw.release, typeof(VoidMethodVoid));
release(ptr);
I have to call a C++ DLL from my C# program.
I'm trying to do it using PInvoke - everything works fine in VS2005\ 2008, but after migration to VS 2010, I get this exception:
PInvokeStackImbalance was detected
Message: A call to PInvoke function
'sampleFunc' has unbalanced the stack.
This is likely because the managed
PInvoke signature does not match the
unmanaged target signature. Check that
the calling convention and parameters
of the PInvoke signature match the
target unmanaged signature.
This is the original C++ prototype:
typedef struct {
unsigned short field1;
unsigned short field2;
} sInfo;
_declspec(dllexport) int sampleFunc(sInfo *info, char *txt);
and here is the C# code:
[StructLayout(LayoutKind.Sequential)]
struct SInfo
{
//[MarshalAs(UnmanagedType.U1)] //also tried with the MarshalAs attr. Didn't help.
public ushort field1;
//[MarshalAs(UnmanagedType.U1)]
public ushort field2;
};
[DllImport("sampleModule.dll", CharSet=CharSet.Ansi)]
public static extern int sampleFunc(ref SInfo info, [MarshalAs(UnmanagedType.LPStr)] string txt);
I've tried it also with IntPtr instead of the ref SInfo, but got the same result...
Any help will be appreciated,
Thank you all!
Hard to see how this could have worked before. The C++ declaration doesn't declare the calling convention, the default is __cdecl unless overridden in the C++ project with the /Gz compile option. You have to tell the P/Invoke marshaller:
[DllImport("sampleModule.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int sampleFunc(ref SInfo info, string txt);
This probably has to do with how your packing the struct. The default Pack size is 8, so its probably thinking you have too many bytes. Try setting the Pack size to 2 (16 bit aligned) and see if that helps:
[StructLayout(LayoutKind.Sequential, Pack=2)]
Alternatively you can specify the offsets like this:
[StructLayout(LayoutKind.Explicit)]
public struct struct1
{
[FieldOffset(0)]
public ushort a; // 2 bytes
[FieldOffset(2)]
public ushort b; // 2 bytes
}
Here is a good reference on packing
In an attempt to learn to use PInvoke in C#, I'm a little unsure how to handle various cases with pointers involving simple value types.
I'm importing the following two functions from an unmanaged DLL:
public int USB4_Initialize(short* device);
public int USB4_GetCount(short device, short encoder, unsigned long* value);
The first function uses the pointer as an input, the second as an output. Their usage is fairly simple in C++:
// Pointer as an input
short device = 0; // Always using device 0.
USB4_Initialize(&device);
// Pointer as an output
unsigned long count;
USB4_GetCount(0,0,&count); // count is output
My first attempt in C# results in the following P/Invokes:
[DllImport("USB4.dll")]
public static extern int USB4_Initialize(IntPtr deviceCount); //short*
[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, IntPtr value); //ulong*
How do I use these functions in C# in the same way as the C++ code above? Is there a better way to declare these types, perhaps using MarshalAs?
If the pointer is to a single primitive type and not an array, use ref / out to describe the parameter
[DllImport("USB4.dll")]
public static extern int USB4_Initialize(ref short deviceCount);
[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, ref uint32 value)
In these examples out is probably more appropriate but either will work.
The .NET runtime can do a lot of that conversion (referred to as "marshaling") for you. While an explicit IntPtr will always do EXACTLY what you tell it to, you can likely substitute the ref keyword for a pointer like that.
[DllImport("USB4.dll")]
public static extern int USB4_Initialize(ref short deviceCount); //short*
[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, ref short value); //ulong*
You can then call them like this:
short count = 0;
USB4_Initialize(ref count);
// use the count variable now.