[英]I have a c++ code that needs to be translated to c#, almost done (I think) but need help with P/Invoke to use an unmanaged dll
I'm having a hard time with a project (in c++.net) that needs to be converted to c#. 我在一个需要转换为c#的项目(在c ++。net中)遇到了麻烦。 This project uses an API written in unmanaged c++.
该项目使用以非托管c ++编写的API。 I have the API´s .lib, .dll and .h, and want to call the dll functions from inside .net using p/invoke.
我有API的.lib,.dll和.h,并且想使用p / invoke从.net内部调用dll函数。 Ok, here's the code: First, there is this c++ struct
好的,这是代码:首先,有一个c ++结构
typedef struct {
struct Item {
int condition;
char name[80];
Item::Item()
{
reset();
}
void Item::reset()
{
condition = 0;
memset(name, 0, sizeof(name));
}
};
bool channel[32];
int itemCount;
Item item[5];
} TEXTIN_QUERY_CONDITION, *LPTEXTIN_QUERY_CONDITION;
which translated to c# would have been something like this (I guess, correct me if I'm wrong): 转换成C#可能是这样的(我想,如果我错了,请纠正我):
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct TEXTIN_QUERY_CONDITION
{
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst = 32, ArraySubType = System.Runtime.InteropServices.UnmanagedType.Bool)]
public bool[] channel;
public int itemCount;
public ItemClass[] item; //how define the size (5)???
}
and my ItemClass looks like this: 我的ItemClass看起来像这样:
class ItemClass
{
public Item item = new Item();
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential,
CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
public struct Item
{
public int condition;
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr,
SizeConst = 80)]
public string name;
}
public ItemClass()
{
reset();
}
public void reset()
{
item.condition = 0;
item.name = new string('0', 80);
}
}
In .h file there's a definition for this function: 在.h文件中,有此函数的定义:
bool search_queryTextIn(const LPBYTE condition, bool queryNext);
which I think translates to c# like this: 我认为这样翻译成C#:
[DllImport("search.dll")]
protected static extern bool search_queryTextIn(
[MarshalAs(UnmanagedType.LPArray)] byte[] condition,
[MarshalAs(UnmanagedType.I1)] bool queryNext);
Then, inside the c++ code, the function is called using this: 然后,在c ++代码内部,使用以下函数调用该函数:
void queryTextIn(TEXTIN_QUERY_CONDITION& condition, bool queryNext)
{
_searchCore.queryTextIn(&condition, queryNext);
}
and the _searchCore.queryTextIn method is defined like this: _searchCore.queryTextIn方法的定义如下:
bool SearchSDK_Class::queryTextIn(const LPTEXTIN_QUERY_CONDITION condition, bool queryNext)
{
return ::search_queryTextIn((LPBYTE)condition, queryNext);
}
which calls the function defined in .h above. 它将调用上面.h中定义的函数。 My major problem is how to call this function from c#.
我的主要问题是如何从c#调用此函数。 First, I created an instance of the TEXTIN_QUERY_CONDITION struct, but I don't know how to pass a pointer to this struct as a parameter, and how convert it to a byte array to finally call the function... Please, please, are there some kind soul that help me figure out that last bit to call the unmanaged function?
首先,我创建了TEXTIN_QUERY_CONDITION结构的实例,但我不知道如何将指向该结构的指针作为参数传递,以及如何将其转换为字节数组以最终调用该函数。有什么好心的灵魂可以帮助我找出调用非托管函数的最后一点吗? Thanks a million.
太感谢了。
The item
member is not a pointer, so the ItemClass
translation needs to be a value type, not a class. item
成员不是指针,因此ItemClass
转换需要是值类型,而不是类。 Then use the MarshalAs
attribute and specify SizeConst
just like you did with channel. 然后,使用
MarshalAs
属性并指定SizeConst
,就像处理channel一样。 Or use the fixed
keyword . 或使用
fixed
关键字 。
Well, the only thing that worked for my struct was the following: 好吧,对我的结构唯一起作用的是以下内容:
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst = 5, ArraySubType = System.Runtime.InteropServices.UnmanagedType.Struct)]
public Item[] item;
So I'm able to create an instance of TEXTIN_QUERY_CONDITION struct. 因此,我能够创建TEXTIN_QUERY_CONDITION结构的实例。 But now I'm trapped in how to define the c++ function:
但是现在我陷入了如何定义c ++函数的陷阱:
bool search_queryTextIn(const LPBYTE condition, bool queryNext);
Currently I have this: 目前我有这个:
[DllImport("search.dll")]
protected static extern bool search_queryTextIn(
[In,Out] IntPtr condition,
[MarshalAs(UnmanagedType.I1)] bool queryNext);
and I'm calling that function as: 并且我将该函数称为:
TEXTIN_QUERY_CONDITION condition;
//... here I fill the struct with data...
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HeaderStruct.TEXTIN_QUERY_CONDITION)));
IntPtr c = new IntPtr(result.ToInt32());
Marshal.StructureToPtr(condition, c, true);
c = new IntPtr(c.ToInt32() + Marshal.SizeOf(typeof(HeaderStruct.TEXTIN_QUERY_CONDITION)));
search_queryTextIn(c ,queryNext);
Is my approach of using IntPtr correct? 我使用IntPtr的方法正确吗? Sometimes the unmanaged DLL works, sometimes doesn't.
有时非托管DLL有效,有时无效。 When it works, it returns an IntPtr pointing to another struct.
当它工作时,它返回一个IntPtr指向另一个结构。 How can I convert this pointer info back to that struct?
如何将指针信息转换回该结构? I'm trying Marshal.PtrToStructure() but no luck, it fills the struct with garbage... Thanks for any help.
我正在尝试Marshal.PtrToStructure(),但没有运气,它在结构中充满了垃圾...感谢您的帮助。
maybe this could be helpful to you : 也许这可能对您有帮助:
Implementing an unmanaged C++ interface callback in C#/.Net 在C#/。Net中实现非托管C ++接口回调
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.