使用指针调用非托管代码(更新) [英] Calling un-managed code with pointer (Updated)

查看:160
本文介绍了使用指针调用非托管代码(更新)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我要开始我说我是一个相对较新的C#,我在一个小的可能是潜水太深太快了 - 但我喜欢挑战自己,这是我的学习方式(快)

First, let me start off my saying that I am a relative newcomer to C#, and I am probably diving in a little too deep too quick - but I like to challenge myself, and this is the way I learn (quickly)

我有一个项目,使调用到非托管C ++ DLL。该包装和大多数的调用都工作正常,所以我知道我有多么的一切关系的基本结构一起确定,但有是给我适合一个特定的电话。该API调用需要指向一个结构,它包含的配置数据的列表

I have a project that makes calls out to an unmanaged C++ dll. The wrapper and most of the calls are working OK, so I know that I have the basic structure of how everything ties together OK, but there is one specific call that is giving me fits. The API call requires a pointer to a structure, which contains a list of configuration data.

下面是调用:

m_status = m_XXXXBox.SetConfig(m_channelId, ref SCONFIG_LIST);



在哪里SCONFIG_LIST是包含数据的结构...

Where SCONFIG_LIST is the structure containing the data...

问题具体涉及SCONFIG_LIST

The issue specifically relates to SCONFIG_LIST

下面是直接的文档从规范这个API:

Here is the documentation directly from the spec for this API :

Points to the structure SCONFIG_LIST, which is defined as follows:
typedef struct
{
unsigned long NumOfParams; /* number of SCONFIG elements */
SCONFIG *ConfigPtr; /* array of SCONFIG */
} SCONFIG_LIST
where:
NumOfParms is an INPUT, which contains the number of SCONFIG elements in the array
pointed to by ConfigPtr.
ConfigPtr is a pointer to an array of SCONFIG structures.
The structure SCONFIG is defined as follows:
typedef struct
{
unsigned long Parameter; /* name of parameter */
unsigned long Value; /* value of the parameter */
} SCONFIG

下面是2的结构,我在C#中定义的:

Here are the 2 structures that I defined in C#:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SConfig
{
    public int Parameter;
    public int Value;
}



[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SConfig_List
{
    public int NumOfParams;
    // public List<SConfig> sconfig = new List<SConfig>();  // This throws compile time error
    public List<SConfig> sconfig;
}



我知道你不能在结构领域的初始化,但我似乎无法弄清楚如何初始化在结构中的SCONFIG外部...
以下是调用方法段

I know you can not have field initializers in structs, but I cant seem to figure out how to initialize the sconfig in the struct externally... Here is snippet from the calling method

      SConfig_List myConfig = new SConfig_List();
      SConfig configData = new SConfig();

      configData.Parameter = 0x04;
      configData.Value = 0x10;
      myConfig.NumOfParams = 1;
      myConfig.sconfig.Add(configData);

这在运行时对象引用不设置到对象的实例$ B抛出一个错误$ b我明白这个错误,因为SCONFIG尚未初始化 - 我只是无法弄清楚如何做到这一点......

This throws an error at runtime of "object reference not set to an instance of an object" I understand this error because sconfig has not been initialized - I just cant figure out how to do that....

所以,我的下一个想法就是来解决这个问题,我只想创造SCONFIG_LIST结构像这样(没有名单内) - 我对这个的理由是,我现在没有初始化的对象,我可以多次调用了NumOfParams = 1到DLL,而不是NumOfParams> 1,并具有穿过的结构数据的dll的循环。

So my next thought was to get around this, I would just create the SCONFIG_LIST struct like this (without the list inside) - My reasoning for this is that I now do not have to initialize the object, and I could just make multiple calls to dll with a NumOfParams = 1, rather than NumOfParams > 1 and having the dll loop through the struct data.

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SConfig_List
{
    public int NumOfParams;
    public SConfig sconfig;
}

这是我如何调用该方法

configData.Parameter = 0x04;
configData.Value = 0x10;
myConfig.NumOfParams = 1;
myConfig.sconfig.Parameter = configData.Parameter;
myConfig.sconfig.Value = configData.Value;

m_status = m_XXXXBox.SetConfig(m_channelId, ref myConfig);

这摆脱了错误的这一点,现在调用DLL $的实际方法b $ b本章仍然围绕编组几个问题/问题,但在这里它是:

This got rid of the errors to this point, now on the the actual method that calls the dll There are still several questions / issues surrounding the Marshalling, but here it is:

public XXXXErr SetConfig(int channelId, ref SConfig_List config)
{
    unsafe
    {
        IntPtr output = IntPtr.Zero;
        IntPtr input = Marshal.AllocHGlobal(Marshal.SizeOf(config));
        Marshal.StructureToPtr(config, input, true);

        XXXXErr returnVal = (XXXXErr)m_wrapper.Ioctl(channelId, (int)Ioctl.SET_CONFIG, input, output);
        return returnVal;
    } 
}

这得到过去所有的初始设置中没有错误,但是当我尝试实际调用的DLL我得到一个错误:试图读取或写入受保护的内存。这通常是指示其他内存已损坏。

This gets past all of the initial setup without error, but when I try to actually invoke the dll I get an error : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

我知道这是一个拗口,我真的不知道要问什么,因为我相信有在这个帖子中的多个问题,但让我在正确的轨道上的任何想法?

I know this is a mouthful, and I really don't even know exactly what to ask as I am sure there are multiple issues within this post, but any ideas on getting me on the right track?

我在这一点上我很茫然试过这么多东西,我只是需要一些方向。我不是在寻找一个为我做这种式的答案,而是一个解释,也许在得到这个做了一些三分球。正如所有的事情,我相信有完成任务的多种方式 - 也许一个可行的办法,但不是好的形式,以及更长更复杂的方式,可能是更好的做法

I have tried so many things at this point I am at a loss, and I just need some direction. I am not looking for a "do this for me" type answer, but rather an explanation and maybe some pointers on getting this done. As with all things, I am sure there are multiple ways of accomplishing the task - maybe a way that works, but is not good form, and a longer more complicated way that may be "better practice"

任何和所有的建议/意见将不胜感激。如果我排除需要帮我解决这个谜语让我知道,我会提供我所能任何相关数据。

Any and all suggestions / comments will be greatly appreciated. And if I excluded any relevant data that is required to help me solve this riddle let me know and I will provide what I can.

我要感谢的答复为止。
我一直在尝试各种组合,试图解决这个自己,但我没有任何运气至今。我已经发现了不少的方式,无论如何,不​​要上班,: - )

I want to thank the responses so far. I have been trying every combination to try and resolve this myself but I have not had any luck so far. I have found quite a few ways that do NOT work, however :-)

我已经试过的不安全的不同组合 - 的MarshalAs,StructLayout等几其他的事情,我在网上找到,现在我求饶。

I have tried various combinations of "unsafe" - "MarshalAs", "StructLayout" and several other things I found on the web, now I am begging for mercy.

我已经成功地实现了其他几个调用该非托管的DLL,但所有的人都用简单的整数指针等。我的问题是传递指向包含数组的Struct另一个结构。如果你看看我原来的问题的最顶端,你可以看到从DLL文件以及它是如何想的事情有条理。没有返回值,我只是想通过这个dll传递一些配置设置到设备。

I have successfully implemented several other calls to this unmanaged dll, but all of them use simple integer pointers etc. My problem is passing the pointer to a Struct containing an array of another struct. If you look at the very top of my original question you can see the documentation from the dll and how it wants thing structured. There is NO return value, I am merely trying to pass some configuration settings to a device through this dll.

我要发表我的整个项目的一个框架,使也许我可以让别人通过这个过程握住我的手,并希望帮助别人,将来试图解决这种类型的问题也是如此。

I am going to post a framework of my entire project so that maybe I can get someone to hold my hand through this process, and hopefully help others in the future trying to solve this type of issue as well.

我明白任何及所有提前帮助......我想获得这个解决了,而我仍然有一些头发离开

I appreciate any and all help in advance... I want to get this solved while I still have some hair left

下面是包装的骨架(不显示的所有功能)

Here is skeleton of Wrapper (not all functions displayed)

using System;
using System.Runtime.InteropServices;

namespace My_Project
{
    internal static class NativeMethods
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);
    }

    internal class APIDllWrapper
    {
        private IntPtr m_pDll;

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate int APIIoctl(int channelId, int ioctlID, IntPtr input, IntPtr output);
        public APIIoctl Ioctl;
        //extern "C" long WINAPI APIIoctl
        //(
        //unsigned long ChannelID,
        //unsigned long IoctlID,
        //void *pInput,
        //void *pOutput
        //)

        public bool LoadAPILibrary(string path)
        {
            m_pDll = NativeMethods.LoadLibrary(path);

            if (m_pDll == IntPtr.Zero)
                return false;

            pAddressOfFunctionToCall = NativeMethods.GetProcAddress(m_pDll, "APIIoctl");
            if (pAddressOfFunctionToCall != IntPtr.Zero)
                Ioctl = (APIIoctl)Marshal.GetDelegateForFunctionPointer(
                                                                                        pAddressOfFunctionToCall,
                                                                                        typeof(APIIoctl));
            return true;
        }

        public bool FreeLibrary()
        {
            return NativeMethods.FreeLibrary(m_pDll);
        }
    }
}


And Here is the class that defines the hardware I am trying to communicate with
    namespace My_Project
{
    public class APIDevice
    {
        public string Vendor { get; set; }
        public string Name { get; set; }

        public override string ToString()
        {
            return Name;
        }
    }
}


Interface
    using System.Collections.Generic;

namespace My_Project
{
    public interface I_API
    {
        APIErr SetConfig(int channelId, ref SConfig_List config);
    }
}



包含API代码的实际类 - 这是错误的是,我知道,我怎么有IntPtrs现在是不正确的 - 但是,这显示什么,我试图做

The actual Class containing the API Code - this is where the error is, I know that how I have the IntPtrs now is Not correct - But this displays what I am trying to do

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace My_Project
{
    public class API : I_API
    {
        private APIDevice m_device;
        private APIDllWrapper m_wrapper;

        public APIErr SetConfig(int channelId, ref SConfig_List config)
        {
            IntPtr output = IntPtr.Zero;
            IntPtr input = Marshal.AllocHGlobal(Marshal.SizeOf(config));
            Marshal.StructureToPtr(config, input, true);

            APIErr returnVal = (APIErr)m_wrapper.Ioctl(channelId, (int)Ioctl.SET_CONFIG, input, output);
            return returnVal;             
        }       
    }
}

下面是包含定义类对于结构体我使用

Here is class containing the definitions for the Structs I am using

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace My_Project
{
    public enum APIErr
    {
        STATUS_NOERROR = 0x00,
        ERR_BUFFER_EMPTY = 0x10,
        ERR_BUFFER_FULL = 0x11,
        ERR_BUFFER_OVERFLOW = 0x12
    }

    public struct SConfig
    {
        public int Parameter;
        public int Value;
    }

    public struct SConfig_List
    {
        public int NumOfParams;
        public SConfig[] sconfig;

        public SConfig_List(List<SConfig> param)
        {
            this.NumOfParams = param.Count;
            this.sconfig = new SConfig[param.Count];
            param.CopyTo(this.sconfig);
        }
    }
}

和最后 - 实际应用通过包装调用的dll

And finally - the actual application calling the dll through the wrapper

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using My_Project;

namespace Test_API
{
    public class Comm
    {
        private I_API m_APIBox;
        APIErr m_status;
        int m_channelId;
        bool m_isConnected;

        public Comm(I_API apiInterface)
        {
            m_APIBox = apiInterface;
            m_isConnected = false;
            m_status = APIErr.STATUS_NOERROR;
        }

        public bool ConfigureDevice()
        {
            SConfig tempConfig = new SConfig();

            tempConfig.Parameter = 0x04;
            tempConfig.Value = 0x10;
            SConfig_List setConfig = new SConfig_List(tempConfig);

            m_status = m_APIBox.SetConfig(m_channelId, ref setConfig);
            if (m_status != APIErr.STATUS_NOERROR)
            {
                m_APIBox.Disconnect(m_channelId);
                return false;
            }
            return true;
        }
    }
}



我希望这是足够的,而不信息超载
我将是所提供的任何帮助或建议,真的很感谢

I hope this is enough without an information overload I will be really really grateful for any help or advice offered

感谢

-lee

推荐答案

我开始另一个线程,因为我是问错了问题,由于缺乏经验,我

I started another thread because I was asking the wrong question due to my inexperience

的工作方案是在这里。

struct和IntPtr的元帅阵列

感谢您的帮助。

- 李

这篇关于使用指针调用非托管代码(更新)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆