将VC++动态链接库封装成C#可以用的动态链接库步骤

  1. VS2008下,File->new->Progect,Project types选择Visual C++下面的CLR,Templates选择Class Library。键入项目名称PXI3223Base(C#用的动态链接库的名称),选择路径,点击OK完成项目新建。
  2. 将VC下的PXI3223DeciceDll.h(API头文件), PXI3223DeviceDll.lib(静态库)复制到项目路径下的PXI3223Base文件夹下;同时将PXI3223DeviceDll.dll(C++下动态链接库)复制到C:\WINDOWS\system32下。在VS2008项目名PXI3223Base上右键,菜单Add->Existing Item..选择PXI3223DeciceDll.h,将PXI3223DeciceDll.h添加到项目目录中。
  3. 编写PXI3223Base.h及PXI3223Base.cpp,语法参考C++/cli标准。
  4. 编译,在项目路径\Debug下会生成PXI3223Base.dll。将此DLL文件放在C:\WINDOWS\system32下,在C#测试项目中添加引用,即可使用该动态链接库。
  5. 注意:在c++的API头文件PXI3223DeciceDll.h中,要添加#include “windows.h”。
  6. 下面为PXI3223DeciceDll.h的代码
#define  PXI3223_API __declspec(dllexport)__stdcall
#else
#define  PXI3223_API __stdcall
#endif

#include "windows.h"

#define MaxNum  4

struct ADConfigParam
{
    UINT channelSelect;         //通道选择
    UINT sampleRate;            //采样速率
    UINT sampleCount;           //采样次数
    UINT fifoLevel;             //fifo中断级别
    UINT range;                 //量程范围
};
//通道补偿参数
struct CompParam
{
    BOOL    bCompOffset[8];
    BOOL    bCompGain[8];
    float   fCompOffset[8];
    float   fCompGain[8];
};
typedef enum _RET_STATUS
{
    RET_SUCCESS            =  0,
    RET_DEVICE_INITIALFAIL = -1,
    RET_DEVICE_NONEXIST    = -2,
    RET_DEVICE_CLOSEFAIL   = -3,
    RET_EVENT_CREATEFAIL   = -4,
    RET_IRP_SENTFAIL       = -5,
    RET_PARAM_ILLEGAL      = -6,
    RET_UNKOWN_ERROR       = -7,
    RET_Thread_CreateFail  = -8,
    RET_Synchronize_error  = -9,
    RET_Thread_AlreayRuning =-0xa,
    RET_ALLOCATEMEM_FAIL    = -0xB,
    RET_Thread_NotRunning   = -0x0c,
    RET_EVENT_REGISTER_FAIL = -0x0d,
    RET_THREAD_SETPRI_FAIL  = -0x0e,
    RET_THREAD_RESUME_FAIL  = -0x0f

}RETSTATUS,*PRESTATUS;

//#ifdef __cplusplus
//extern "C" {
//#endif

//打开板卡。
//devNum:设备号,从0开始
BOOLEAN PXI3223_API PXI3223_OpenCard(DWORD DevNum);

//功能:  关闭板卡
//参数:  DevNum      板卡号
//返回值:true        操作成功
//        false       操作失败
BOOLEAN  PXI3223_API PXI3223_Close(DWORD DevNum);


//复位,对9054寄存器复位
//devNum:设备号,从0开始
BOOLEAN  PXI3223_API  PXI3223_ResetAll(DWORD DevNum);




////////////////////////////IO输入输出函数,两个函数不能同时使用,视硬件情况而定///////////////////////////////////////
//DevNum:设备号,从0开始
// outputData:低七位分别对应七个通道,从低位到高位分别为1-7通道,如outputData=0x03则通道IO0和通道IO1为高
BOOLEAN PXI3223_API PXI3223_IOOutput(DWORD DevNum, UINT outputData);

//DevNum:设备号,从0开始
// *pInputData:低七位分别对应七个通道,从低位到高位分别为1-7通道,如*pInputData=0x03则通道IO0和通道IO1为高
BOOLEAN PXI3223_API PXI3223_IOInput(DWORD DevNum, UINT* pInputData);



/////////////////////////////AD函数/////////////////////////////////////////////
//DevNum: 设备号,从0开始
//ADConfigParam param:
// struct ADConfigParam
// {
//  UINT channelSelect;     //通道选择,低八位每一位对应一个通道,选中即为1,未选中为0.如0x0003,则是通道1,通道2被选中
//  UINT sampleRate;        //采样速率,范围为1-20的整数,分别对应1M-20M,sampleRate=1代表采样速率为1M,以此类推
//  UINT sampleCount;       //采样次数。指开启AD采集后,每个选中的通道可采集的数据数量。由于硬件缓存原因,8个通道加在一起最大采样次数为64M。另外采样次数必                                        //须是偶数。
//  UINT fifoLevel;         //fifo中断级别,即缓存FIFO中触发中断的数据数量界限,最大可设置为(8K - 1),且表示FIFO中双字的数据数量,因为FIFO位宽32位,AD采集                                        //位宽为14位,故存储时两个AD数据构成32位存储在FIFO中,这也是采样次数必须是偶数的原因。如设置为1,表示缓存FIFO中含有两个AD数据后                                       //触发中断
//  UINT range;            //量程范围,0代表-1——1量程,1代表-10——10量程
// };
BOOLEAN PXI3223_API PXI3223_ADConfig(DWORD DevNum, ADConfigParam param, CompParam compParam);

//开始接收函数(DMA中断)
// devNum:设备号,从0开始
// pRecvData: 接收数据的数组指针,数组大小应为recvNum*recvFrame个FLOAT
// recvNum  : 选中的通道个数,通道2,3,7被选中则为3,范围为1-8
// recvFrame: 每个通道读取数据数量。为跟配置信息中的采样次数相匹配,此值必须为偶数,且不能大于配置信息中采样数据数量,否则函数一直处于等待状态
RETSTATUS PXI3223_API PXI3223_DmaRecv(DWORD devNum, FLOAT* pRecvData, USHORT recvNum, USHORT recvFrame);

//开始采集函数,在PXI3223_ADConfig之后调用,在PXI3223_DmaRecv之前调用,
//调用顺序应为PXI3223_ADConfig->PXI3223_ADStart->PXI3223_DmaRecv(or PXI3223_RecvData)
//devNum:设备号,从0开始
RETSTATUS PXI3223_API PXI3223_ADStart(DWORD DevNum);

//AD停止采集;devNum:设备号,从0开始
RETSTATUS PXI3223_API   PXI3223_ADStop(DWORD DevNum);
//#ifdef __cplusplus
//}
//#endif`

PXI3223Base.h代码

#pragma once

#pragma comment(lib, "PXI3223DeviceDLL.lib")

#include "PXI3223DeviceDLL.h"

using namespace System;


namespace PXI3223Base {

    public ref class PXI3223
    {
        // TODO: Add your methods for this class here.

    private:
        DWORD devNum;//设备号
    public:
        bool isOpened;//标志板卡是否打开状态

        //构造函数
        PXI3223(int _devNum)
        {
            devNum = _devNum;
            isOpened = false;
        }
        //打开板卡
        //返回值:true表示打开成功,isOpened状态变为true
        //        若板卡已经打开,也返回true。但会抛出"PXI3223卡已经打开!"异常
        bool Open();

        //关闭板卡
        //返回值:true表示成功关闭。isOpened状态变为false
        //      若板卡已经关闭,则返回true。但会抛出"PXI3223卡已关闭!"异常
        bool Close();

        //复位板卡
        //返回值:true表示成功复位板卡。
        //        false表示复位板卡失败或板卡尚未打开(同时抛出"PXI3223卡尚未打开!"异常)。
        bool ResetAll();

        ////////////////////////////IO输入输出函数,两个函数不能同时使用,视硬件情况而定///////////////////////////////////////
        //IO输出
        //outputData:低七位分别对应七个通道,从低位到高位分别为1-7通道,如outputData=0x03则通道IO0和通道IO1为高
        //返回值:true表示IO输出成功,
        //      false表示IO输出失败或板卡尚未打开(同时抛出"PXI3223卡尚未打开!"异常)。
        bool IOOutput(UINT outputData);

        //IO输入
        //返回值:低七位分别对应七个通道,从低位到高位分别为1-7通道,如*pInputData=0x03则通道IO0和通道IO1为高
        //      返回0x80表示IO输入失败,或板卡尚未打开(同时抛出"PXI3223卡尚未打开!"异常)。
        UINT IOInput();

        //AD转换开启
        //返回值:开启成功返回枚举型的RET_SUCCESS
        //      失败返回失败状态码。尚未打开板卡返回RET_DEVICE_INITIALFAIL,同时抛出"PXI3223卡尚未打开!"异常。
        bool ADStart();

        //AD转换停止
        //返回值:成功停止AD返回枚举型的RET_SUCCESS
        //      失败返回失败状态码。尚未打开板卡返回RET_DEVICE_INITIALFAIL,同时抛出"PXI3223卡尚未打开!"异常。
        bool ADStop();

        //配置AD
        //ADConfigParam param:AD配置参数
        // struct ADConfigParam
        // {
        //  UINT channelSelect;     //通道选择,低八位每一位对应一个通道,选中即为1,未选中为0.如0x0003,则是通道1,通道2被选中
        //  UINT sampleRate;        //采样速率,范围为1-20的整数,分别对应1M-20M,sampleRate=1代表采样速率为1M,以此类推
        //  UINT sampleCount;       //采样次数。指开启AD采集后,每个选中的通道可采集的数据数量。由于硬件缓存原因,8个通道加在一起最大采样次数为64M。另外采样次数必                                        //须是偶数。
        //  UINT fifoLevel;         //fifo中断级别,即缓存FIFO中触发中断的数据数量界限,最大可设置为(8K - 1),且表示FIFO中双字的数据数量,因为FIFO位宽32位,AD采集                                        //位宽为14位,故存储时两个AD数据构成32位存储在FIFO中,这也是采样次数必须是偶数的原因。如设置为1,表示缓存FIFO中含有两个AD数据后                                       //触发中断
        //  UINT range;            //量程范围,0代表-1——1量程,1代表-10——10量程
        // };
        //CompParam compParam通道补偿参数
        //struct CompParam
        //{
        //  BOOL    bCompOffset[8]; //是否偏执补偿
        //  BOOL    bCompGain[8];   //是否增益补偿
        //  float   fCompOffset[8]; //偏置补偿参数(输入0V时的差值)
        //  float   fCompGain[8];   //增益补偿参数(输入满量程时的实测值)
        //};
        //返回值:true表示成功配置AD
        //      false表示AD配置失败或或板卡尚未打开(同时抛出"PXI3223卡尚未打开!"异常)。
        bool ADConfig(UINT channelSelect, UINT sampleRate, UINT sampleFrame, UINT fifoLevel, UINT range,
            array^ bCompOffset, array^ bCompGain, array<float>^ fCompOffset, array<float>^ fCompGain);

        //读取AD转换数据
        //recvChNum打开的通道个数
        //recvFrame每个通道AD转换次数
        //返回值:接收成功返回读取的AD浮点值,容量为recvChNum * recvFrame的数组
        //      接收失败返回空指针nullptr,若未打开板卡,抛出"PXI3223卡尚未打开!"异常。
        array<float>^ DmaRecv(USHORT recvChNum, USHORT recvFrame);

    };
}

PXI3223Base.cpp代码

#include "stdafx.h"

#include "PXI3223Base.h"

namespace PXI3223Base {
    bool PXI3223::Open()
    {
        if(isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡已经打开!");
            return true;
        }
        else
        {
            if(!PXI3223_OpenCard(devNum))
            {
                throw gcnew InvalidOperationException("打开PXI3223卡失败!");
                return false;
            }
            else
            {
                isOpened = true;
                return true;
            }
        }
    }
    bool PXI3223::Close()
    {
        if(!isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡已关闭!");
            return true;
        }
        else
        {
            if(!PXI3223_Close(devNum))
            {
                throw gcnew InvalidOperationException("关闭PXI3223卡失败!");
                return false;
            }
            else
            {
                isOpened = false;
                return true;
            }
        }

    }

    bool PXI3223::ResetAll()
    {
        if(!isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡尚未打开!");
            return false;
        }
        else
        {
            if(!PXI3223_ResetAll(devNum))
            {
                throw gcnew InvalidOperationException("整体复位失败!");
                return false;
            }
            return true;
        }
    }

        ////////////////////////////IO输入输出函数,两个函数不能同时使用,视硬件情况而定///////////////////////////////////////
        // outputData:低七位分别对应七个通道,从低位到高位分别为1-7通道,如outputData=0x03则通道IO0和通道IO1为高
    bool PXI3223::IOOutput(UINT outputData)
    {
        if(!isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡尚未打开!");
            return false;
        }
        else
        {
            if(!PXI3223_IOOutput(devNum, outputData))
            {
                throw gcnew InvalidOperationException("PXI3223卡IO输出失败!");
                return false;
            }
            return true;
        }
    }
        //返回值:低七位分别对应七个通道,从低位到高位分别为1-7通道,如*pInputData=0x03则通道IO0和通道IO1为高
    UINT PXI3223::IOInput()
    {
        if(!isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡尚未打开!");
            return 0x80;
        }
        else
        {
            UINT inputData = 0x80;
            if(!PXI3223_IOInput(devNum, &inputData))
            {
                throw gcnew InvalidOperationException("PXI3223卡IO输入失败!");
                inputData = 0x80;
            }
            return inputData;
        }
    }

    //DevNum: 设备号,从0开始
    //ADConfigParam param:
    // struct ADConfigParam
    // {
    //  UINT channelSelect;     //通道选择,低八位每一位对应一个通道,选中即为1,未选中为0.如0x0003,则是通道1,通道2被选中
    //  UINT sampleRate;        //采样速率,范围为1-20的整数,分别对应1M-20M,sampleRate=1代表采样速率为1M,以此类推
    //  UINT sampleCount;       //采样次数。指开启AD采集后,每个选中的通道可采集的数据数量。由于硬件缓存原因,8个通道加在一起最大采样次数为64M。另外采样次数必                                        //须是偶数。
    //  UINT fifoLevel;         //fifo中断级别,即缓存FIFO中触发中断的数据数量界限,最大可设置为(8K - 1),且表示FIFO中双字的数据数量,因为FIFO位宽32位,AD采集                                        //位宽为14位,故存储时两个AD数据构成32位存储在FIFO中,这也是采样次数必须是偶数的原因。如设置为1,表示缓存FIFO中含有两个AD数据后                                       //触发中断
    //  UINT range;            //量程范围,0代表-1——1量程,1代表-10——10量程
    // };
    bool PXI3223::ADConfig(UINT channelSelect, UINT sampleRate, UINT sampleFrame, UINT fifoLevel, UINT range,
            array^ bCompOffset, array^ bCompGain, array<float>^ fCompOffset, array<float>^ fCompGain)
    {
        if(!isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡尚未打开!");
            return false;
        }
        else
        {
            ADConfigParam configParam;
            configParam.channelSelect = channelSelect;
            configParam.sampleRate = sampleRate;
            configParam.sampleCount = sampleFrame;
            configParam.fifoLevel = fifoLevel;
            configParam.range = range;

            CompParam compParam;

            for(int i = 0; i < 8; i++ )
            {
                compParam.bCompOffset[i] = bCompOffset[i];
                compParam.bCompGain[i] = bCompGain[i];
                compParam.fCompOffset[i] = fCompOffset[i];
                compParam.fCompGain[i] = fCompGain[i];
            }

            if(!PXI3223_ADConfig(devNum, configParam, compParam))
            {
                throw gcnew InvalidOperationException("PXI3223卡AD配置失败!");
                return false;
            }
            return true;
        }
    }

    array<float>^ PXI3223::DmaRecv(USHORT recvChNum, USHORT recvFrame)
    {
        if(!isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡尚未打开!");
            return nullptr;
        }
        else
        {
            array<float>^ pRecvData = gcnew array<float>(recvChNum * recvFrame);
            pin_ptr<float> pADBuf = &pRecvData[0];
            RETSTATUS retStatus = PXI3223_DmaRecv(devNum, pADBuf, recvChNum, recvFrame);
            if(retStatus != RET_SUCCESS)
            {
                throw gcnew InvalidOperationException("PXI3223卡读取AD数据失败!");
                return nullptr;
            }
            return pRecvData;
        }
    }

    bool PXI3223::ADStart()
    {
        if(!isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡尚未打开!");
            return false;
        }
        else
        {
            RETSTATUS retStatus = PXI3223_ADStart(devNum);
            if(retStatus != RET_SUCCESS)
            {
                throw gcnew InvalidOperationException("开启AD转换失败!");
                return false;
            }
            return true;
        }
    }

    bool PXI3223::ADStop()
    {
        if(!isOpened)
        {
            throw gcnew InvalidOperationException("PXI3223卡尚未打开!");
            return false;
        }
        else
        {
            RETSTATUS retStatus = PXI3223_ADStop(devNum);
            if(retStatus != RET_SUCCESS)
            {
                throw gcnew InvalidOperationException("开启AD转换失败!");
                return false;
            }
            return true;
        }
    }
}

你可能感兴趣的:(c++-cli)