26年10月之后对此前Plus的收费全部免费(不再有Plus),仅保留的3项作为Pro版收费,
主要是对符号后期处理问题上提供专业的解决方案

[具体有]
1、以cpp源文件作为封装的模块含有类导出时在链接期捕获去除其EXP导出表
2、C++源文件、Lib库命名空间改编
3、C库改编到MSVC++符号

相关联问题阐述的文章:
关于导出整个C++类.mht、用户模块版本隔离问题.mht、lib库文件不一定总是被提取符号.mht

 


[EXP类符号在链接期移除]

对模块工程以源码形式直接打包出bec

注:由于没有参与任何编译并没有lib文件可供生成后改编

在主程中引入该模块

注意:这不是在后期把exe的整个导出表给删掉,而是精准把所有引入的模块各个.cpp源文件进行统计,在VS链接期拦下对其生成的obj把其内部的导出指令给删除

此外,在Release(LTCG优化)下也支持做了处理

 

 


[子模块的C++自动化改编命名空间]

你是否在传统易语言编程中遇到某些支持库不兼容导致xxx符号已在某obj这被定义这样的错误提示

其实本质上易语言的底层用的还是Win32-VC库代码链接那套规则体系

该系统性或后期解决方案之前在 用户模块版本隔离问题.mht 中已经演示(若主程中遇到符号冲突问题可新建一个模块工程并导入之前套用该可能冲突的子模块后根据演示中的弹出提示自动完成改编)

 

现在这里下面还要说说 排除命名空间符号的这个编辑列表的作用:

起因还要先说说这个 白易模块注释级指令.mht#beExcludeNamespaceSymbol

假若我一个子模块中引用了外部的全局类型(如Bytes),那么使用到它的函数参数本身其类型就不应该给它改编(如果改编那么在模块m1里看到的应该是_Mm1::Bytes而不是全局那个唯一的Bytes)

在白易中区分其外部类型的方案则是全部分析该模块内所有的文件及其符号,确定在这些文件中没找到符号定义时则认为是外部符号类型,上面这里MyStruct属于模块内符号(当然也支持另开别的cpp文件去定义)可找得到定义则默认会参与改编。

还要注意,改编仅发生在模块引入到的另一个模块工程中被做成子模块。

目前这里已经自动识别出Bytes了(在该编辑框中你还可以自行补充不需要改编的符号:函数名、类型名)

确认改编后,可直接使用:

 

 


[子模块的C库改编到MSVC++符号]

这个要改编的情况就十分复杂了(事实上不单单是要改编函数签名,连同它引用到的结构体也要正确纳入进来),所以我也找来了libcurl这个重量级库(内部包含zlib、openssl、libssh等属于综合性模块)直接上改编验证其可靠性

新建模块工程,然后将curl_native.bec(可在BEModG中找到curl_native自行打包到zip)导入作为其子模块

点击【C库符号改编】即可全自动化进行(模块中包含x86和x64的lib)

当然我还是要说一下注意事项,按【完成】后Lib库中C语言比例降到一部分来到82.2%

这不是我们改编工具的问题,而是有部分C语言确实没改编上;

原因是C++的符号改编必须拥有其完整的可靠头文件声明,而Curl_MD5_init这个在我这一版curl它没有公开这个头文件,那么这部分依旧保持C风格符号(但白易改编工具这里还给其加上随机前缀以防冲突,另外连同其他obj内未定义的仅声明所引用符号也一并改了,故整个过程是安全可靠的)

 

之后根据需要可再进行C++的【确认改编空间】、【取消改编空间】。

我这里就直接【取消改编空间】为例,然后下面是测试代码

#include "stdafx.h"
#include "mkcurl.h" //由MakeBEC.exe自动生成
//此main.cpp仅用作模块测试不参与头文件的解析生成
//若想排除特定cpp文件的解析可在工程属性页-生成事件
//改写MakeBEC.exe参数-excludesrc=多文件[需加空格]
 
struct ResponseBuffer
{
    size_t totalBytes;
    size_t keptBytes;
    char   prefix[4096];
};
 
static size_t CurlWriteCallback(char* ptr, size_t size, size_t nmemb, void* userdata)
{
    ResponseBuffer* out = (ResponseBuffer*)userdata;
    const size_t bytes = size * nmemb;
    out->totalBytes += bytes;
 
    size_t remain = sizeof(out->prefix) - 1 - out->keptBytes;
    size_t copyBytes = bytes < remain ? bytes : remain;
    if (copyBytes > 0)
    {
        memcpy(out->prefix + out->keptBytes, ptr, copyBytes);
        out->keptBytes += copyBytes;
        out->prefix[out->keptBytes] = 0;
    }
    return bytes;
}
 
// 同时强制 VC 编译器生成几组复杂公开 API 的引用,继续覆盖 ABI 映射。
auto g_p_inflateBack = &inflateBack;
auto g_p_curl_easy_header = &curl_easy_header;
auto g_p_curl_easy_setopt = &curl_easy_setopt;
auto g_p_curl_easy_getinfo = &curl_easy_getinfo;
auto g_p_curl_ws_send = &curl_ws_send;
 
int main()
{
    CURLcode globalRc = curl_global_init(CURL_GLOBAL_DEFAULT);
    if (globalRc != CURLE_OK)
    {
        printf("curl_global_init failed: %d\n", (int)globalRc);
        return 10;
    }
 
    CURL* curl = curl_easy_init();
    if (!curl)
    {
        printf("curl_easy_init failed\n");
        curl_global_cleanup();
        return 11;
    }
 
    ResponseBuffer response = {};
    response.prefix[0] = 0;
 
    curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com/");
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "BEVCpp-curl-mangle-test/1.0");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
 
    CURLcode rc = curl_easy_perform(curl);
    long httpCode = 0;
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
 
    printf("curl=%d (%s)\n", (int)rc, curl_easy_strerror(rc));
    printf("http=%ld\n", httpCode);
    printf("bytes=%llu\n", (unsigned long long)response.totalBytes);
    printf("prefix=%.200s\n", response.prefix);
 
    curl_easy_cleanup(curl);
    curl_global_cleanup();
 
    if (rc != CURLE_OK)
        return 20;
    if (httpCode < 200 || httpCode >= 400)
        return 21;
    if (response.totalBytes == 0)
        return 22;
    return 0;
}

这里我们成功编译且仅打印前200个字节成功访问带HTTPS的百度,说明curl的改编没有问题。