按以下步骤创建一个最简单的项目,该插件作为一个BIMBase外部命令,执行时弹出一个提示框显示“Hello BIMBase”

1.3.1 下载Visual Studio 2019 版本


图1-2 下载位置

  • 下载完成并打开安装包后,会出现如图1-3所示的Visual Studio Install界面,点击修改,可下载开发所需的工作负荷,一般下载图1-4中4个即可满足大部分开发需求,安装位置可自定义,在工作负荷右侧安装位置选项中修改。
  • 注意,若想使用MFC功能需要勾选使用C++的桌面开发工作负荷中的选项(适用于最新V142生成工具的C++ATL)。

图1-3 Visual Studio Install界面


图1-4 安装相关工作负荷

1.3.2 下载并安装软件及SDK

  • 在PKPM官网(https://www.pkpm.cn )“下载”入口下载BIMBase软件产品(下载“BIMBase建模软件”版本即可)并进安装。

图1-5 软件下载

  • 在BIMBase二次开发网站(https://dev.pkpm.cn )下载BIMBaseSDK版本并进行安装。注意:下载的BIMBase软件产品与BIMBaseSDK版本号应保持一致。

图1-6 SDK下载

  • 安装完SDK后,目录如图1-5所示,Samples中包含了所有的范例,对于范例中的Example.sln稍做配置,如图1-6所示,“调试”的“命令”设置为安装的BIMBase软件exe路径,即可运行起来进行查看。


    图1-7 SDK中相关内容


    图1-8 SDK中范例项目配置

1.3.3 新建项目

  • 打开Visual Studio 2019,单击菜单框“文件”→“新建”→“项目”,打开“新建项目对话框”。如图1-9所示,创建一个自己的项目(MyBIMBase项目)。



图1-9 新建项目对话框

  • 右键设置MyBIMBase项目属性,如表1-1所示。解决方案配置为“Release”,解决方案平台配置为x64;

表1-1 主要环境配置

配置 安装路径
MyBIMBase C\C++->常规->附加库包含目录 [SDK安装路径]\include\; [SDK安装路径]\include\P3DCore\; [SDK安装路径]\include\Share\;
链接器->常规->附加库目录 [SDK安装路径]\Lib\Release\; [SDK安装路径]\Lib\Release\Share\BcgFrame; [SDK安装路径]\Lib\Release\Share; [SDK安装路径]\Lib\Release\P3DCore;
配置属性->调试->命令 [建模软件安装路径]\BIMBASE.exe
  • stdafx.h中添加平台头文件引用,stdafx.cpp中添加lib引用,可直接从范例中拷贝(在Visual Studio 新版平台工具集中,预编译头文件由原来的stdafx.h修改为pch.h),以下为相关代码。
#include <vector>
#include <map>
#include <algorithm>
//平台相关
#include "BPExportMacros.h"
#include "PKPMExportMacros.h"
#include "P3DDC/P3DDCAPI.h"
#include "P3DGeomBase/P3DGeomBasePublicAPI.h"
#include "P3DGeomObject/P3DGeomObjectPublicAPI.h"
#include "JsonCpp/JsonCppAPI.h"
#include "BPBase/BPBaseAPI.h"
#include "BPData/BPDataAPI.h"
#include "BPDataCore/BPDataCoreDef.h"
#include "BPDataCore/BPDataCoreAPI.h"
#include "BPDataCore/BPPlacement.h"
#include "BPDataCore/BPDomainDataInitManager.h"
#include "BPDisplay/BPDisplayAPI.h"
#include "BPInteraction/BPInteractionAPI.h"
#include "BPFrame/BPFrameAPI.h"
#include "BPSolidCore/BPSolidCoreAPI.h"
#include "BPBase/BPPlatformAPI.h"
#include "BPUIFrameWork/BPUIFrameWorkAPI.h"
#include "BPUIFrameWork/BPUIFrameWorkUtil.h"
using namespace p3d;
#include "BPPrimaryElement/BPPrimaryGeomAPI.h"
#include "Share/TgGe/TgGe.h"

代码1-2 头文件列表(片段)

#pragma comment (lib, "P3DCore/P3DDC.lib")
#pragma comment (lib, "P3DCore/P3DGeomBase.lib")
#pragma comment (lib, "P3DCore/P3DGeomObject.lib")
#pragma comment (lib, "BPDataCore.lib")
#pragma comment (lib, "Share/TgGe.lib")
#pragma comment (lib, "BPPlatform.lib")
#pragma comment (lib, "BPSolidCore.lib")
#pragma comment (lib, "BPDataExt.lib")
#pragma comment (lib, "P3DCore/JsonCpp.lib")
#pragma comment (lib, "BPUIFrameWork.lib")
#pragma comment (lib, "BPApp.lib")
#pragma comment (lib, "BPDataCore.lib")
#pragma comment (lib, "BPPrimaryElement.lib")
#pragma comment (lib, "BPPluginManager.lib")

代码1-3 lib库列表(片段)

  • 入口插件dll注册
    在入口DLL的MyBIMBase.cpp文件中继承BPPluginFactory类,实现onLoadPluginonUnLoadPlugininitPluginInformationloadPluginAssembly,并通过BPPluginManager类进行注册、卸载,如示例代码1-4所示。
class ExamplesPluginEntry :public BIMBase::Plugin::BPPluginFactory 
{
public:
    ExamplesPluginEntry() {};
    virtual ~ExamplesPluginEntry() {};
protected:
    //提供加载响应时机,重载但不用实现
    virtual void _onLoadPlugin(CWnd* curMainFrame) override
    {
        std::vector<wstring> vecAssembly = BIMBase::Plugin::BPPluginManager::getInstance().getCurPluginAssmebly();
        for (auto it : vecAssembly)
        {//模块加载
            loadPluginAssembly(it);
        }
    }
    //提供卸载响应时机,重载但不用实现
    virtual void _onUnLoadPlugin(::BIMBase::Core::BPProjectR curProject) override
    {
    }
    //返回插件的信息,重载但不用实现
    virtual void _initPluginInformation(::BIMBase::Plugin::PluginInformation& pluginInformation) override
    {
        pluginInformation.m_wsPluginDescribe = L"二次开发";
    }
};
static ExamplesPluginEntry _pluginEntry;
PBBIM_IMPLEMENT_EXTENSION_MODULE(entryDll);

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    // 如果使用 lpReserved,请将此移除
    UNREFERENCED_PARAMETER(lpReserved);

    if (dwReason == DLL_PROCESS_ATTACH)
    {
        if (!entryDll.AttachInstance(hInstance))
            return 0;
        //插件注册
        BIMBase::Plugin::BPPluginManager::getInstance().registerPlugin(&_pluginEntry);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        //插件反注册
        BIMBase::Plugin::BPPluginManager::getInstance().unRegisterPlugin();
        entryDll.DetachInstance();
    }
    return 1;   // 确定
}

代码1-4:入口DLL的dllmain.cpp插件加载部分

表1-2 BPPluginFactory接口说明

方法 描述
onLoadPlugin 工程事件–加载插件时触发
onUnLoadPlugin 工程事件–卸载插件时触发
initPluginInformation 获取初始化插件的信息–回调调用
loadPluginAssembly 加载插件模块,插件入口调用

表1-3 BPPluginManager接口说明

方法 描述
registerPlugin 插件的注册
unRegisterPlugin 插件的反注册–注销事件、卸载事件、对话框资源释放
unLoadPlugin 插件卸载
getCurPluginAssmebly 获取当前插件需要加载的模块
addCurPluginAssmebly 添加当前插件需要加载的模块

1.3.4 代码编写

  • 在完成上述步骤后,下面可以开始编写具体代码。创建一个新的HelloBIMBase.cpp文件,并将复制以下代码。
void HelloBIMBase()
{
     AfxMessageBox(L"Hello BIMBase!");
}
AutoDoRegisterFunctionsBegin
BPToolsMessager::registerFun(_T("HelloBIMBase"), &HelloBIMBase);
AutoDoRegisterFunctionsEnd

1.3.5 插件加载

  • 安装SDK时,会自动在C:\ProgramData\PKPM\BIMBase\Plugins\SDK类别\SDK版本号\c++plugin路径下放置一个默认的plugin文件(安装完SDK后,C盘会默认配置,注意有些电脑ProgramData文件夹是隐藏状态),用于插件加载。其中路径里SDK类别为不同类型的软件,如lite/pro/Traffic版本等,lite是指BIMBase建模软件Lite-模型浏览器这款软件;pro是指BIMBase建模软件,例如BIMBase建模软件2024R1.0;Traffic是指交通版建模软件,例如BIMBase建模软件2024R1.0[T]。示例中下载的BIMBase建模软件2024R1.0,所以插件加载在pro这个路径下。SDK版本号,即SDK安装包上所标识版本号。plugin文件放置位置示意如图1-10所示,以及plugin文件配置(代码1-4所示),可通过修改plugin配置文件来加载自己的插件。范例中基于的SDK版本号为V1.2,加载具体流程参考附录一

图1-10 plugin文件放置位置

<?xml version="1.0" encoding="utf-8" ?>
<BIMBasePlugins>
   <Plugin>
       <!-- 插件名称。标签不可缺少,值不可为空。插件名称要小于128字符-->
       <Name>MyBIMBase</Name>
       <!-- 插件描述。标签不可缺少,值可以为空-->
       <Description>MyBIMBase</Description>
       <!-- 开发商信息。标签不可缺少,值可为空-->
       <VendorId>PKPM</VendorId>
       <!-- 插件开发标识。标签不可缺少,值不可为空。需要去dev.pkpm.cn申请pluginId-->
       <PluginId>FFA5E1D6-CCE7-4CE1-B1EA-FDEF6D8FC13D</PluginId>
       <!-- 插件研发基于BIMBase的版本,默认不用修改 -->
       <PluginSDKVersion>1.2.5</PluginSDKVersion>
       <!-- 插件的版本记录。标签不可缺少,值不可为空。格式要求x.x.x,由插件研发者维护,便于管理插件版本-->
       <PluginVersion>1.0.0</PluginVersion>
       <!-- 插件入口DLL。标签不可缺少,值不可为空。填写入口插件dll全路径-->
       <EntryAssembly>D:\MyBIMBase\MyBIMBase\bin\Release\MyBIMBase.dll</EntryAssembly>
       <!-- 其他Dll列表。需填写dll全路径。标签可缺少,值可以为空-->
       <AssemblyList>
           <Assembly></Assembly>
       </AssemblyList>
       <!-- Schema的路径。标签不可缺少,值可以为空。填写schema文件所在的文件夹路径,若所填写的路径为无效路径,则插件加载失败-->
       <SchemaPath>D:\SDK版本\BIMBase建模软件2024R1.0_SDK V1.2\Samples\schemaDemo\</SchemaPath>
       <!-- Schema的版本。标签不可缺少,值可以为空。格式要求x.x,若是不符合规则,插件则加载信息失败。注意SchemaPath与SchemaVersion要么同时填写,要么同时为空,否则也会导致插件加载失败-->
       <SchemaVersion>1.0</SchemaVersion>
       <!-- 界面配置文件。标签可缺少,值可以为空。若需要在软件启动界面配置新模块,则需要配置MajorConfig文件(SDK包中有模板),并在此指定全路径-->
       <!-- MajorConfig文件命名格式要求:MajorConfig_XXX.xml,前缀MajorConfig+自定义名称-->
       <MajorConfig>D:\SDK版本\BIMBase建模软件2024R1.0_SDK V1.2\Samples\config\MajorConfig_secDevCPP.xml</MajorConfig>
       <!-- 加载菜单。标签可缺少,值可以为空。填写菜单dll的全路径-->
       <Ribbon>D:\SDK版本\BIMBase建模软件2024R1.0_SDK V1.2\Samples\C++Examples\BPExamples\RibbonDesignCPPDemo\Release\RibbonDesignCPPDemo.dll</Ribbon>
       <!-- 插件作用的模块,对应MajorConfig中的NAME标签。标签不可缺少,值不可为空。指定后可在特定模块加载插件。多个使用","隔开,如“电气,BIMBase”,若为All,则作用所有模块-->
       <ActionChDomainKeys>BIMBase,二次开发CPP</ActionChDomainKeys>
       <!-- 插件加载状态。标签不可缺少,值可为空,空则为false -->
       <LoadStatus>true</LoadStatus>
    </Plugin>
</BIMBasePlugins>

代码1-4 plugin文件配置示意

1.3.6 执行插件

  • 启动BIMBase,在命令行输入已经注册的命令“HelloBIMBase”,执行后将弹出一个对话框,如图1-11所示。
图1-11 “Hello BIMBase”对话框

1.3.7 调试插件

  • 在编码、运行过程中可能会遇到各种各样的问题,因此需要进行断点调试检查当前变量和对象的状态来定位问题。
  • 编译之后,可直接按F5可进行调试。
  • 此外,还可以在BIMBase启动后,在Visual Studio的“调试”菜单下选择“附加到进程”,见图1-12。在打开的“附加到进程”对话框中选择“BIMBase.exe”,然后单击“附加”按钮。

图1-12 附加到进程对话框