【问题标题】:Can you use std::string in a 3rd party dll?您可以在第 3 方 dll 中使用 std::string 吗?
【发布时间】:2016-10-24 05:45:30
【问题描述】:

我一直在寻找我的问题的答案,但似乎大多数人都对跨 .dll 边界传递 std::string 感兴趣。但我对在我正在创建的 .dll 中的类中使用 std::string 更感兴趣。

我正在向我所在论坛上的一群人发布我的 .dll(电子邮件),所以我的问题是你能否在 .dll 中使用 std::string 而没有编译器需要相同的限制,版本、CRT 需要相同等。

您能否举例说明什么是不安全的,什么是安全的?

示例:“下载者”使用 SetSender 功能是否安全?

邮件.h

class _declspec(dllexport) Mail {

    struct ENVELOPE {
        std::wstring SenderEmail; //Should the type be LPWSTR or can it safely be std::wstring
        LPWSTR SenderName;

    }Envelope;

public:
    int SetSender(LPWSTR SenderEmail);
    Mail();
    ~Mail();

};

邮件.cpp

#include "stdafx.h"
#include "Mail.h"

int CoffeeBeans::Mail::SetSender(LPWSTR Email) {
 //Pass LPWSTR instead of std::wstring across .dll boundary

    if (Email == nullptr || lstrcmp(Email, L"") == 0) {
        throw L"Email was either nullptr or empty.";
    }

    this->Envelope.SenderEmail = SenderEmail;
    return 0;


}

【问题讨论】:

  • 我会说 C 字符串肯定是安全的。那么为什么不传递一个只读的 C 字符串呢?
  • 我过去使用过一个 .dll,当我使用一个采用 std::string(mysqlc++ 库)的函数时,我的程序崩溃了,我必须重新编译 dll 才能使其工作。
  • @PaulStelian 谢谢,但你说得非常正确,我一直养成传递 wchar* 而不是 const wchar * 的坏习惯。
  • 其他人已经解决了您的实际问题,但我只想提一下,据我所知,throw 出于同样的原因并不安全。在 DLL 中抛出 是安全的,只要在 DLL 中捕获即可。当编译器不同时,您不能安全地传递 std::string accross_the_DLL_boundary(在任一方向),也不能安全地跨边界传递异常。
  • @GavinLock 有趣,我不知道这一点,太糟糕了,因为我更喜欢使用抛出而不是返回错误。谢谢,它避免了未来的头痛!

标签: c++ dll


【解决方案1】:

使用指向字符串缓冲区的指针,如LPWSTRwchar_t* 等,只要您的 dll 代码没有调用未指定的行为(内存分配正确,指针已初始化,您不是将指针传递给本地缓冲区等)。只要您的 dll 和主机使用相同的 CRT 版本,使用std::string 将是安全的。如果版本不同,您的字符串可能会在任何执行阶段导致访问冲突(通常发生在字符串销毁时)。您可以通过分发 dll 源或为所有现有 CRT 编译不同的 dll 版本来确保 CRT 匹配(例如,Oracle 为其OCCI 库执行此操作)。如果客户端不使用 C++,这种方法当然行不通。

【讨论】:

  • 这正是我今天使用 3rd 方 DLL 所经历的。但是有没有关于这个问题的任何 MS 文档?
  • @Trantor 我没有看到任何此类文档。
猜你喜欢
  • 2011-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多