简体   繁体   English

我有一个C ++代码,需要转换为C#,差不多完成了(我认为),但是需要P / Invoke的帮助才能使用非托管dll。

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM