从Delphi返回动态数组到C#和C++

来源:互联网 发布:诺基亚jar软件下载 编辑:程序博客网 时间:2024/06/05 21:00

     经过很多尝试, Delphi/pascal无法将array of integer这样的数组返回给C#,只能传数组的地址过去, C#以IntPtr类型的参数接收, 然后通过Marshal将指针所指的内容复制出来 

    delphi的dll声明:

function dumpRegisters(out pvOut: PInteger; out pvSize: word): boolean; stdcall;export;begin   sendDebug('dumpRegisters.');   result:=false;   if (gdm=nil) then begin      sendDebug('dumpRegisters, failed');      exit;   end;   pvOut:=@gdm.FRegisterValues[0];   pvSize:=length(gdm.FRegisterValues);   result:=true;   sendDebugFmt('dumpRegisters, OK, out:%p, size:%d',[pvOut,pvSize]);end;                                                                    

C#的import声明:

public static extern void setRoutines(IntPtr pvRoutines);    [DllImport("modbusapi.dll", EntryPoint = "dumpRegisters", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]    public static extern byte dumpRegisters(out IntPtr pvAddr,        out UInt16 pvSize);
然后通过这个函数转换:

public static int[] IntPtr2RegisterData(IntPtr pvAddr,ushort pvSize)    {        int[] lvRegisters = new int[pvSize];        Marshal.Copy(pvAddr, lvRegisters,0, pvSize);        return lvRegisters;    }
例子:

 IntPtr lvPtr;            ushort lvSize;            int[] lvRet = null;            if (ModBus.dumpRegisters(out lvPtr, out lvSize) != 0)                lvRet = ModBus.IntPtr2RegisterData(lvPtr, lvSize);                StringBuilder sb = new StringBuilder();                for (int i = 0; i < lvSize; i++)                {                        sb.Append(String.Format("Register:{0}, value: {1}\r\n", i, lvRet[i]));                }                textBox1.AppendText(sb.ToString());            }

====================

而用VC调用,则可以做到无缝连接,直接引用指针:

定义function指针:

typedef bool(__stdcall* _dumpRegisters)(PINT&, WORD&);

bool ModBus::readRegisters(PINT& pvOut, WORD& pvSize) {if (mHnd == 0) return false;//_dumpRegisters dumpRegisters = (_dumpRegisters)GetProcAddress(mHnd, "dumpRegisters");_dumpRegisters dumpRegisters = (_dumpRegisters)GetProcAddress(mHnd, "dumpRegisters");WORD lvSize = 0;PINT lvAddr = NULL;if (dumpRegisters(lvAddr, lvSize)) {pvOut = lvAddr;pvSize = lvSize;}}
调用:

PINT lvRegisters = NULL;WORD lvSize = 0;char lvOut[1024*10];int lvLen = 0;if (modbus.readRegisters(lvRegisters,  lvSize)) {for (int i = 0; i < lvSize; i++) {try {lvLen += sprintf_s(lvOut + lvLen, 1024 * 10 - lvLen, "Register:%d, Value:%d \r\n", i, lvRegisters[i]);}catch (const std::exception& e){}}CString lvT(lvOut);ed_log.SetWindowTextW(lvT);}



上述方法应该于内存在dll里面管理的情况, 如果内存块在主程序里面先申请的,调用如下 :

dll 代码:

function dumpRegisters(pvOut: PInteger; out pvSize: word): boolean; stdcall;export;begin   sendDebug('dumpRegisters.');   result:=false;   if (gdm=nil) then begin      sendDebug('dumpRegisters, failed');      exit;   end;   //pvOut:=@gdm.FRegisterValues[0];   pvSize:=length(gdm.FRegisterValues);   sendDebugFmt('dumpRegisters, source addr:%p,  target addr:%p,size:%d',[@gdm.FRegisterValues[0],pvOut,pvSize]);   sendDebugFmt('before size:%d',[pvSize]);   move(gdm.FRegisterValues[0],pvOut^,sizeof(Integer)*pvSize); //复制数据到主程序的内存pvOut   sendDebugFmt('after size:%d',[pvSize]);   result:=true;   sendDebugFmt('dumpRegisters, OK, out:%p, size:%d',[pvOut,pvSize]);end;

VC的调用:

typedefbool(__stdcall* _dumpRegisters)(PINT, WORD&);
_dumpRegisters dumpRegisters = (_dumpRegisters)GetProcAddress(mHnd, "dumpRegisters");PINT lvAddr = NULL;mRegisterSize = mRoutines->getRegisterSize();PINT mRegisters = new int[mRegisterSize];dumpRegisters(mRegisters, pvSize); .....delete [] mRegisters;


C#的调用:

    [DllImport("modbusapi.dll", EntryPoint = "dumpRegisters", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]    private static extern byte dumpRegisters([In, Out]    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]  int[] pvAddr,        out UInt16 pvSize);UInt16 lvSize = routines.getResiterSize();        int[] registers = new int[lvSize];        dumpRegisters(registers, out lvSize);


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 登录微信手机收不到验证码怎么办 美图t8冲一会电就发烧怎么办 美图t8系统不小心升级了 怎么办 美图手机看相册视频就会变黑怎么办 苹果4s屏幕唤醒速度慢怎么办 美图m4换电池后不显示卡怎么办 美图手机久没充电再充没反应怎么办 美图6s开不开机怎么办 苹果4s照片不能拍照黑屏怎么办 美图手机开机键坏了怎么办 金立金刚二手机烧卡怎么办 金立金刚手机开不开机怎么办 小米4手机拆机信号不好怎么办 荣耀自带游览器无法正常打开怎么办 苹果4s电池越来越不耐用怎么办 苹果4s电池不耐用了怎么办 苹果手机4s电池不耐用怎么办 红米4s电池不耐用怎么办 32位app私密相册打不开怎么办 红米手机取卡针断手机里了怎么办 我差评了客服打电话骂我怎么办 顺丰快递在预计时间没有回来怎么办 同款商品比京东便宜怎么办 京东自营不支持7天退货怎么办 天猫买了一个月的电动车坏了怎么办 发票号码和机打号码不一致怎么办 交电费的本子弄丢了怎么办 快递正在派件中发现地址错了怎么办 快递当天送达当天签收还算延怎么办 深圳国税公众号预约取号公司怎么办 社保买了停了2年怎么办 qq号被冻结申请不回来了怎么办 qq号被冻结 手机密保忘了怎么办 微信账号封了2天怎么办 买qq号被申诉找回了怎么办 收到了京东白条的催款通知单怎么办 成都买房社保不够两年怎么办18年 电话号码给人设置成骚扰电话怎么办 找不到领导电话不接短信不回怎么办 微信账号被别人手机号冻结了怎么办 微信冻结了手机号也让人换了怎么办