通用枚举值...

    // 本枚举融合 Autodesk.AutoCAD.Runtime.LispDataType
// Autodesk.AutoCAD.EditorInput.PromptStatus
public enum EnumBufCode
{
// resbuf元素的类型
None = , //没有结果 回车耶
Double = , //实数 Real
Point2d = , //2维点
Int16 = , //短整数 Short
Angle = , //角度
Text = , //字符串 String
ObjectId = , //实体名称 Ename
SelectionSet = , //选择集名 PickSet
Orientation = , //方向
Point3d = , //3维点
Int32 = , //长整数 Long
Void = , //空白符号
ListBegin = , //list begin
ListEnd = , //list end
DottedPair = , //点对
Nil = , //nil(空表)
Dxf0 = , //DXF代码0仅适用于ads_bListldlist
T_atom = , //T(原子) Resbuf = , //resbuf Modeless = , //被无模式对话中断
Other = , // 错误返回代码
OK = , //请求成功,用户输入值有效 Norm
Error = -,//其他一些错误
Cancel = -,//用户取消请求-Ctl-C
RejectRequest = -,//AutoCAD拒绝请求-无效
FailureLink = -,//链接失败-Lisp可能已经死了
Keyword = -,//从getxxx()例程返回的关键字
Inputtruncated = -,//输入并不都适合缓冲区
}

首先是传参型lisp的定义,它在低版本有个问题,就是所有的返回值都要用表包裹着,而高版本就修复了这个问题.

为了所有版本统一,返回值应该统一成 ResultBuffer ,在lisp再(car 返回值).... 我这里既有 ResultBuffer,又有object返回,供各位参考.

        //传参型lisp的定义:传点
//复制到命令栏运行: (Test_AddLine (getpoint))
[LispFunction("Test_AddLine")] //注意: 这里不是command!
public static ResultBuffer AddLine(ResultBuffer rbArgs)
{
Database db = Acap.DocumentManager.MdiActiveDocument.Database;
Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor; Point3d p1 = Point3d.Origin;
Point3d p2 = Point3d.Origin;
if (rbArgs != null)
{
foreach (TypedValue rb in rbArgs)
{
try
{
//ed.WriteMessage(Environment.NewLine + "rb.ToString()=" + rb.ToString());
//ed.WriteMessage(Environment.NewLine + "rb.TypeCode.ToString()=" + rb.TypeCode.ToString());
//ed.WriteMessage(Environment.NewLine + "rb.Value.ToString()=" + rb.Value.ToString()); var str = rb.Value.ToString();
str = str.Substring().Substring(, str.Length - ); var pts = str.Split(',');
p2 = new Point3d(double.Parse(pts[]), double.Parse(pts[]), double.Parse(pts[]));
}
catch
{ }
}
}
var line = new Line(p1, p2);
using (Transaction tr = db.TransactionManager.StartTransaction())
{
var acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
var acBlkTblRec = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
// line.SetDatabaseDefaults();设置数据库默认值
acBlkTblRec.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
tr.Commit();
}
var rbrtn = new ResultBuffer(new TypedValue[]
{
new TypedValue((int)EnumBufCode.ObjectId, line.ObjectId),
new TypedValue((int)EnumBufCode.Point3d, p1),
new TypedValue((int)EnumBufCode.Point3d, p2)
});
ed.WriteMessage(Environment.NewLine + " rbrtn=" + rbrtn.ToString());
ed.WriteMessage(Environment.NewLine);
return rbrtn; //返回值此处有图元名
} //传参型lisp的定义:加法
//复制到命令栏运行: (Test_MyAdd 1 2 3)
[LispFunction("Test_MyAdd")] //注意: 这里不是command!
public static object Test_MyAdd(ResultBuffer args) //高版本这里可以返回double,但是08只能返回ResultBuffer
{
var ds = new List<double>();
if (args != null)
{
foreach (TypedValue rb in args)
{
try
{
var a = double.Parse(rb.Value.ToString());
ds.Add(a);
}
catch
{ }
}
} double number = ;
foreach (var item in ds)
{
number += item;
} //08只能返回ResultBuffer 会返回表内数字(6.0)
//高版本可以返回其他的
var rbrtn = new ResultBuffer(new TypedValue[]
{
new TypedValue((int)EnumBufCode.Double, number),
}); var dotPair = new ResultBuffer(new TypedValue[] {
new TypedValue((int)EnumBufCode.ListBegin, -),
new TypedValue((int)EnumBufCode.Int16, ),
new TypedValue((int)EnumBufCode.Int16, ),
new TypedValue((int)EnumBufCode.DottedPair, -),
}); #if AC2008
return rbrtn; //但是08只能返回ResultBuffer 会返回(6.0)
#else
return number; //高版本这里可以返回double 会返回6.0
#endif } //传参型lisp的定义:选择集
//复制到命令栏运行: (Test_ssget (ssget))
[LispFunction("Test_ssget")] //注意: 这里不是command!
public static object Test_ssget(ResultBuffer args)
{
//var dt = new List<object>();
var ds = new List<object>();
if (args != null)
{
foreach (TypedValue rb in args)//{((5007,(((-2181752),Crossing,0,)((-2181760),Crossing,0,))))}
{
try
{
//dt.Add(rb.TypeCode);
ds.Add(rb.Value);
}
catch
{ }
}
} var tl = new List<TypedValue>();
foreach (var item in ds)
{
tl.Add(new TypedValue((int)EnumBufCode.SelectionSet, item));
}
var rbrtn = new ResultBuffer(tl.ToArray());
return rbrtn;
} //传参型lisp的定义:点对
//复制到命令栏运行: (Test_dotPair 0 100)
[LispFunction("Test_dotPair")] //注意: 这里不是command!
public static object Test_dotPair(ResultBuffer args)
{
var ds = new List<object>();
if (args != null)
{
foreach (TypedValue rb in args)//{((5007,(((-2181752),Crossing,0,)((-2181760),Crossing,0,))))}
{
try
{
ds.Add(rb.Value);
}
catch
{ }
}
} var ls = new List<TypedValue>(); ResultBuffer dotPair = null;
if (ds.Count == )
{
ls.Add(new TypedValue((int)EnumBufCode.ListBegin, -)); ls.Add(new TypedValue((int)EnumBufCode.Int16, ds[]));
if (short.TryParse(ds[].ToString(), out short num))
{
ls.Add(new TypedValue((int)EnumBufCode.Int16, num));
ls.Add(new TypedValue((int)EnumBufCode.DottedPair, -));
dotPair = new ResultBuffer(ls.ToArray());
}
}
return dotPair; //返回点对表
}

在c#读取和赋值lisp变量的值 ,测试命令: Test_setLisp

#if !HC2020
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.EditorInput;
using GrxCAD.Geometry;
using GrxCAD.ApplicationServices;
using GrxCAD.Runtime;
using GrxCAD.Colors;
using GrxCAD.GraphicsInterface;
using Viewport = GrxCAD.DatabaseServices.Viewport;
using Application = GrxCAD.ApplicationServices.Application;
#endif using System.Runtime.InteropServices;
using System; namespace JoinBox.CommandLisp
{
// 操作lisp赋值
// https://blog.csdn.net/qq_21489689/article/details/80630817
// 我验证了2008和2019,32位 DllImport("accore.dll" 好像不对,没有环境验证 public static class LStructure
{
//LSP变量的写入-64位
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", EntryPoint = "acedPutSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedPutSym64(string args, IntPtr result); #if AC2008
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acad.exe", EntryPoint = "acedPutSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedPutSym32(string args, IntPtr result);
#else
//没有环境验证
//LSP变量的写入-32位
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", EntryPoint = "_acedPutSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedPutSym32(string args, IntPtr result);
#endif /// <summary>
/// 设置Lisp变量值
/// </summary>
/// <param name="name">变量名</param>
/// <param name="rb">变量值</param>
static int SetLispSym(string name, ResultBuffer rb)
{
int ret = ;
//判断系统是32位还是64位
switch (Marshal.SizeOf(typeof(IntPtr)))
{
case :
{
ret = AcedPutSym32(name, rb.UnmanagedObject);
}
break;
case :
{
ret = AcedPutSym64(name, rb.UnmanagedObject);
}
break;
}
return ret;
} //LSP变量的读取-64位
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", EntryPoint = "acedGetSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedGetSym64(string args, out IntPtr result); #if AC2008
//LSP变量的读取-32位
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acad.exe", EntryPoint = "acedGetSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedGetSym32(string args, out IntPtr result);
#else
//没有环境验证
//LSP变量的读取-32位
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", EntryPoint = "_acedGetSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedGetSym32(string args, out IntPtr result);
#endif /// <summary>
/// 获取Lisp变量值
/// </summary>
/// <param name="name">变量名</param>
/// <returns>变量值,如果失败则为空</returns>
static ResultBuffer GetLispSym(string name)
{
IntPtr ip;
//判断系统是32位还是64位
switch (Marshal.SizeOf(typeof(IntPtr)))
{
case :
{
int status = AcedGetSym32(name, out ip);
if (status == (int)EnumBufCode.OK && ip != IntPtr.Zero)
{
return ResultBuffer.Create(ip, true);
}
}
break;
case :
{
int status = AcedGetSym64(name, out ip);
if (status == (int)EnumBufCode.OK && ip != IntPtr.Zero)
{
return ResultBuffer.Create(ip, true);
}
}
break;
}
return null;
} /// <summary>
/// lisp变量赋值
/// </summary>
/// <param name="varName">变量名</param>
/// <param name="varValue">变量值</param>
/// <param name="cEnumRes">变量值类型,原子,字符串等等</param>
public static void SetLspVar(EnumBufCode cEnumRes, string varName, object varValue = null)
{
using (var rb = new ResultBuffer())
{
rb.Add(new TypedValue((int)cEnumRes, varValue));
SetLispSym(varName, rb);
}
} /// <summary>
/// 读取LSP变量
/// </summary>
/// <param name="varName">变量名</param>
/// <returns></returns>
public static object GetLspVar(string varName)
{
object varValue = null;
ResultBuffer rb = GetLispSym(varName);
if (rb != null)
{
foreach (var val in rb)
{
varValue = val.Value;
}
}
return varValue;
} [CommandMethod("Test_setLisp")]
public static void Test_setLisp()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
string varName = "a";
object v;
// 赋值例子
// (setq a "35432")
SetLspVar(EnumBufCode.Text, varName, ""); //返回 "3543252351515"
v = GetLspVar(varName);
ed.Princ(v); // (setq a 35432)
SetLspVar(EnumBufCode.Double, varName, ""); //返回 3543252351515
v = GetLspVar(varName);
ed.Princ(v); // (setq a T)
SetLspVar(EnumBufCode.T_atom, varName, true); //返回 T
SetLspVar(EnumBufCode.T_atom, varName, false); //返回 T
v = GetLspVar(varName);
ed.Princ(v); // (setq a nil)
SetLspVar(EnumBufCode.Nil, varName); //返回 nil
v = GetLspVar(varName);
ed.Princ(v);
} static void Princ(this Editor ed, object var)
{
string varString = "";
if (var == null)
{
varString = "nil";
}
else
{
string type = var.GetType().Name;
switch (type)
{
case "String":
{
varString = var.ToString();
varString = "\"" + varString + "\"";
}
break;
case "Double":
{
varString = var.ToString();
}
break;
case "Boolean":
{
varString = "T"; //返回布尔值都是为true的,不返回才是nil
}
break;
}
}
ed.WriteMessage("\n" + varString);
}
}
}

再来是通过接口发送lisp,这个可以避免用明文方式发送到命令栏,而且它在自动执行函数上面也是同步发送的,很有趣哟: testLisp

#if AC2008 || AC2012
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acad.exe", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acedEvaluateLisp@@YAHPB_WAAPAUresbuf@@@Z")]
private static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); [DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")]
private static extern int AcedInvoke(IntPtr args, out IntPtr result);
#else
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z")]
private static extern int AcedEvaluateLisp(string lispLine, out IntPtr result); [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")]
private static extern int AcedInvoke(IntPtr args, out IntPtr result);
#endif /// <summary>
/// 定义lisp
/// </summary>
/// <param name="arg">lisp语句</param>
/// <returns>缓冲结果,返回值</returns>
public static ResultBuffer RunLisp(string arg)
{
AcedEvaluateLisp(arg, out IntPtr rb);
if (rb != IntPtr.Zero)
{
try
{
var rbb = DisposableWrapper.Create(typeof(ResultBuffer), rb, true) as ResultBuffer;
return rbb;
}
catch
{
return null;
}
}
return null;
} /// <summary>
/// c#发送lisp,这个同步方式可以在自动运行函数上跑,也是同步的
/// </summary>
/// <returns></returns>
[CommandMethod("testLisp")]
public void Cmdtest()
{
string Strlisp = "(setq a 10)";
var res = RunLisp(Strlisp); //有lisp的返回值
}

最后是提供一些发送命令的函数,这里有些备注,他们可以异步发送lisp,有些会导致自动执行时候发送lisp出错,但是却是异步发送的必需品.

    public partial class SendToCad
{
#if AC2006 || AC2007 || AC2008 || AC2009 || AC2010 || AC2011 || AC2012
/// <summary>
/// 发送命令
/// </summary>
/// <param name="strExpr"></param>
/// <returns></returns>
[DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")]
private static extern int Ads_queueexpr(string strExpr);//非同步,这个在08/12发送lisp不会出错,但是发送bo命令出错了.. /// <summary>
/// 发送命令,设置CommandFlags.Session可以同步,
/// 发送lisp也可以,但是非同步,在自动执行函数上面会非同步
/// </summary>
/// <param name="str"></param>
public static void SendLisp(string str)
{
try
{
Ads_queueexpr(str + "\n");
}
catch (Exception ee)
{
//自执行发送lisp都是在最后的(异步执行)
var ed = Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage(Environment.NewLine + "发送命令失败,导致加载失败!");
ed.WriteMessage(Environment.NewLine + "" + ee.Message + Environment.NewLine);
}
} /// <summary>
/// 发送命令
/// </summary>
/// <param name="strExpr"></param>
/// <returns></returns>
[DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedPostCommand@@YAHPB_W@Z")]
private static extern int AcedPostCommand(string strExpr);
#else
/// <summary>
/// 发送命令
/// </summary>
/// <param name="str">发送lisp加载命令</param>
/// <returns></returns>
public static void SendLisp(string str)
{
Document dc = Application.DocumentManager.MdiActiveDocument;
string commands = str + "\n";
try
{
dc.SendStringToExecute(commands, false, false, false);//08所有都flase会有问题,出现报错
}
catch (System.Exception ee)
{
//自执行发送lisp都是在最后的(异步执行)
var ed = dc.Editor;
ed.WriteMessage(ee.Message);
ed.WriteMessage(Environment.NewLine + "发送命令失败,导致加载失败!");
ed.WriteMessage(Environment.NewLine + ee.Message);
}
}
#endif
/// <summary>
/// 发送命令
/// </summary>
/// <param name="str">命令</param>
/// <returns></returns>
public static bool SendCommand(string str) //非同步,这里加载lisp第二个文档有问题...
{
object ActiveDocument = Com.App.GetType().InvokeMember("ActiveDocument", BindingFlags.GetProperty, null, Com.App, null);
object[] commandArray = { str + "\n" };
ActiveDocument.GetType().InvokeMember("SendCommand", BindingFlags.InvokeMethod, null, ActiveDocument, commandArray);
return true;
}
}

最后的最后是一个发送esc的操作,我也不知道为什么要放这里,可能他存在的价值不高...

        //http://www.tiancao.net/blogview.asp?logID=1871&cateID=3&tdsourcetag=s_pcqq_aiomsg
/*
我想从我的非模态对话框的按钮中启动一些命令。我已经发现,对于SendStringToExecute,我应该使用‘\x03’字符而不是^C。
我唯一的问题是,在这种情况下,如果没有运行命令,那么我将在命令窗口,如果单击菜单项时没有运行命令,则菜单的^C^C不会导致* Cancel*出现。
我怎样才能达到同样的目的呢?
解:
你可以查帐CMDNAMES系统变量,根据当前运行的命令数量,可以在命令字符串的开头添加许多转义字符。
这里有一个样本这表明:
*/
[CommandMethod("sendEsc")]
public void SendEsc()
{
//c#非模态窗体发命令
string esc = "";
string cmds = CadSystem.Getvar("CMDNAMES");
if (cmds.Length > )
{
int cmdNum = cmds.Split(new char[] { '\'' }).Length;
for (int i = ; i < cmdNum; i++)
esc += '\x03';
}
Document doc = Application.DocumentManager.MdiActiveDocument;
doc.SendStringToExecute(esc + "_.LINE ", true, false, true);
//设置cad窗口的焦点激活绘图区
//acApp.MainWindow.Focus();
}

最最后,写一下com接口的新旧版本写法:

    public static class Com
{
#if AC2006 || AC2007 || AC2008 || AC2009 || AC2010 || AC2011 || AC2012
public static AcadDocument Adm { get; } = Application.DocumentManager.MdiActiveDocument.AcadDocument as AcadDocument;
#else
public static AcadDocument Adm { get; } = Application.DocumentManager.MdiActiveDocument.GetAcadDocument() as AcadDocument;
#endif #if !HC2020
public static AcadApplication App { get; } = Application.AcadApplication as AcadApplication;
#else
public static GcadApplication App { get; } = Application.AcadApplication as GcadApplication;
#endif
}

cad.net 定义lisp的更多相关文章

  1. Lisp使用Lambda语法

    lamdba 其实就是一个匿名函数. 定义Lisp的lambda语法非常的简单,如下: (lambda ([parameter]) [experssion]) 调用lambda的语法有三种方法,如下: ...

  2. Lisp之根源

    原文:http://www.paulgraham.com/rootsoflisp.html 约翰麦卡锡于1960年发表了一篇非凡的论文,他在这篇论文中对编程的贡献有如 欧几里德对几何的贡献.1 他向我 ...

  3. Lisp之根源 --- 保罗格雷厄姆

    Lisp之根源 --- 保罗格雷厄姆 来源 http://daiyuwen.freeshell.org/gb/rol/roots_of_lisp.html 约翰麦卡锡于1960年发表了一篇非凡的论文, ...

  4. ssget使用方法

    语法: (ssget [sel-method] [pt1 [pt2]] [pt-list] [filter-list]) ssget 的参数均为可选参数,需要注意的是可选参数之间的组合条件.以下语法表 ...

  5. [转载]ssget 用法详解 by yxp

    总结得很好的ssget用法.....如此好文,必须转载. 原文地址: http://blog.csdn.net/yxp_xa/article/details/72229202 ssget 用法详解 b ...

  6. 超文本传输协议-HTTP/1.1

    超文本传输协议-HTTP/1.1(修订版) ---译者:孙超进本协议不限流传发布.版权声明Copyright (C) The Internet Society (1999). All Rights R ...

  7. 借助CAD在Altium Designer中定义不规则PCB外形

    借助绘图软件CAD在Altium Designer中定义不规则PCB外形. 工具/原料 CAD2007 Altium Designer2015 方法/步骤 借助CAD绘制的不规则外形,保存成DXF格式 ...

  8. cad二次开发中各种头的定义

    Database db=HostApplicationServices.WrokingDatabase; Editor ed=Autodesk.AutoCAD.ApplicationService.A ...

  9. cad 画图面板的尺寸大小定义

    输入limits 输入左下角点为 0,0 输入右上角点为大家需要的数  这里为100,50 输入zoom 输入a 就可以实现自定义编辑 注意事项 如果在你已经操作过的图纸上可能会失效 重新建一张图纸就 ...

随机推荐

  1. EF Core中的DB First与Code First

    前言: 大家都习惯在程序中生成对应的model来对数据库进行操作,所以如何快速的生成数据库表的对应model,是基础之一.总结了一下在我的认知中大概是这个结构: Db first方式: 先创建好对应的 ...

  2. lumen 响应宏

    响应宏 laravel 中的响应宏,说明文档中有,lumen的没有找到.于是参考laravel 项目中的响应宏写了个Lumen的 1. 新建文件 App\Providers\ResponseMacro ...

  3. HighChat 动态绑定数据(二)

    也是对最近几天的折线图搞得烦心,看了好多前辈的文章,也总结了一下. 1.先看后台程序,这是我模拟的一些参数 就是一个字符串.没啥好说的 public ActionResult Index2() { s ...

  4. 隐马尔科夫模型(Hidden Markov Models) 系列之四

    转自:http://blog.csdn.net/eaglex/article/details/6430389 前向算法(Forward Algorithm) 一.如果计算一个可观察序列的概率?   1 ...

  5. 02篇ELK日志系统——升级版集群之kibana和logstash的搭建整合

    [ 前言:01篇LK日志系统已经把es集群搭建好了,接下来02篇搭建kibana和logstash,并整合完成整个ELK日志系统的初步搭建. ] 1.安装kibana 3台服务器: 192.168.2 ...

  6. javascript之DOM(四其他类型)

    一.Text类型 文本节点由Text类型表示,指的是可以以字面意思解释的纯文本内容,其中包含HTML代码. nodeType=3 nodeName=#text nodeValue=文本内容 paren ...

  7. PAT 乙级 1048.数字加密 C++/Java

    题目来源 本题要求实现一种数字加密方法.首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 ...

  8. POJ 2516Minimum Cost(最小费用流+特判)

    [题意]: 有N个人,M个仓库,每个人需要物品,个数都等于共同的K,仓库中有对应的K件物品的数量,随后给K个N*M矩阵(小写k, n, m表示K,N,M对应的子集),表明m个仓库到第n个人的位置运送k ...

  9. MapReduce 简单开发

    先给出 maven 依赖配置 <properties> <hadoop.version>2.6.0</hadoop.version> </properties ...

  10. 编译rabbitmq c++客户端

    rabbitmq官网地址 rabbitmq客户端 c++版本地址 rabbitmq客户端 c版本地址 下载c++版本:根据编译说明 Pre-requisites boost-1.47.0 or new ...