关于dll接口函数返回对象(对象里有vector容器)的一个小小小小小小小小小小小小小问题

时间:2022-05-04 08:52:20
我正在用BCB6写一个动态链接库(dll),打算在vc和ActiveX控件里调用。

我要在接口函数里返回一个容器,网上说会有问题,最好是把容器封装到结构体里面,所以我写了一个类,里面含有两个容器,一个vector一个map。

但是当我返回这个类的对象时,并在APP里定义了相同的类,来接收这个对象,可是打印出来之后的东西很乱,是指针指错了内存的症状(我在dll定义的其他毫无相关的变量都打印了出来)。

我想问的是,我这样做是不是可行的。如果可行哪里出错了呢(内存分配?)
如果不行有什么办法传递这个容器呢?(用数组?)

谢谢

15 个解决方案

#1


dll最初是用c标准的,因此对容器,TForm等这些最好用activex来做更通用。

#2


因为我要写TCP通信程序,而我用了VCL里的TSocketClient这个组件,只能创建一个窗体并且做成dll才能被比如VC调用
引用 1 楼 songhtao 的回复:
dll最初是用c标准的,因此对容器,TForm等这些最好用activex来做更通用。

#3


好吧,因为没人回答,所以我尝试用别的方法。
现在我不在接口传递容器了,改用所有对容器的操作都在dll里实现

但又有新的问题,我在dll里定义了一个vector并push_back了一些数据,这个循环结束之后我立即打印出这些数据,但是。。。。。

还是打印乱码?这个貌似是内存管理出了问题,可是。。。我不知道怎么解决????

#4


没人啊。。。。

#5


如果在接口里直接传递STL容器,会发生问题,因为很多STL容器含有静态成员,APP和DLL的内存空间又不一样

在dll里定义了一个vector并push_back了一些数据,这个循环结束之后我立即打印出这些数据
请贴代码

#6


我找到了,我用map容器insert了指针,但是之后立刻删除了,所以会出错。但是现在还有点问题。我大概写下代码
 

whie(getline(infile, ss))
{
    string s1 = ss.substr(...);//...省略了
    string s2 = ss.substr(...);
    map<string, string> map1;
    map1.insert(make_pair(s1, s2));
}
char* str;
map<string, string>::iterator iter = map1.find(str);
if(iter != map1.end())
{
    ...
}

现在的问题是当str = NULL时,会出现异常,如果不为空则可以;这是为什么呢?

引用 5 楼 hind24 的回复:
如果在接口里直接传递STL容器,会发生问题,因为很多STL容器含有静态成员,APP和DLL的内存空间又不一样

在dll里定义了一个vector并push_back了一些数据,这个循环结束之后我立即打印出这些数据
请贴代码

#7


whie(getline(infile, ss)) 

{
  string s1 = ss.substr(...);//...省略了
  string s2 = ss.substr(...);
  map<string, string> map1;
  map1.insert(make_pair(s1, s2));
}
char* str;
map<string, string>::iterator iter = map1.find(str);
if(iter != map1.end())
{
  ...
}

#8


[code=C/C++][whie(getline(infile, ss))
{
  string s1 = ss.substr(...);//...省略了
  string s2 = ss.substr(...);
  map<string, string> map1;
  map1.insert(make_pair(s1, s2));
}
char* str;
map<string, string>::iterator iter = map1.find(str);
if(iter != map1.end())
{
  ...
}]

抱歉,竟然不会插入代码。。。。

#9


BCB6的 std::map 與 VC的std::map , 不同編譯器其STL類的內存布局可能不一樣,這就是DLL中不傳遞STL實例的一個內在原因。

另外,DLL與調用程序使用不同的內存空間,也使得STL類(map vector)的操作要十分小心,不小心就搞壞了內存。

一般不攷慮在DLL接口中傳遞STL類。除非用同一個編譯器。

#10


该回复于2012-03-03 09:49:01被版主删除

#11


但都是设计到字符串,而且还有一一对应的关系,如果不用STL用什么啊 char**?
引用 9 楼 ppower 的回复:
BCB6的 std::map 與 VC的std::map , 不同編譯器其STL類的內存布局可能不一樣,這就是DLL中不傳遞STL實例的一個內在原因。

另外,DLL與調用程序使用不同的內存空間,也使得STL類(map vector)的操作要十分小心,不小心就搞壞了內存。

一般不攷慮在DLL接口中傳遞STL類。除非用同一個編譯器。

#12


whie(getline(infile, ss))
{
  string s1 = ss.substr(...);//...省略了
  string s2 = ss.substr(...);
  map<string, string> map1;
  map1.insert(make_pair(s1, s2));
}
char* str = NULL;
map<string, string>::iterator iter = map1.find(str);//有人说str不能为NULL,为什么啊
if(iter != map1.end())
{
  ...
}

#13


1、有人说str不能为NULL,为什么啊
std::string 構造或賦值,不接受 NULL 指針 可以使用 "" ,但不能用 NULL ;

2、但都是设计到字符串,而且还有一一对应的关系,如果不用STL用什么啊 char**?
如果內部要使用 std::map , 建議DLL寫接口將 std::map 封裝起來,不曝露std::map給外部調用。DLL內使用STL類,需要做黑盒處理,也就是DLL接口中看不見STL模板類。
如果非得將 std::map 曝露出來,那麼你得將 std::map 的頭文件同樣發佈,這就相當於要求別人與你用同樣的 STL 庫版本,而且還得檢查編譯選項,以保障內存佈局一致,函數調用方式一樣。或者你重寫一個可供共用的 std::map 類。

#14


哦,谢谢了。我按照你说的做了,现在可以运行。内部使用STL还是可以的。。

先结贴了。

不过还有另外一个思考,希望还能回答一下哈。

既然内部使用STL可以,那内部使用C++Builder的AnsiString类型行不行呢,而且dll要被VC调用,而且VC那边没有装BCB
谢谢
引用 13 楼 ppower 的回复:
1、有人说str不能为NULL,为什么啊
std::string 構造或賦值,不接受 NULL 指針 可以使用 "" ,但不能用 NULL ;

2、但都是设计到字符串,而且还有一一对应的关系,如果不用STL用什么啊 char**?
如果內部要使用 std::map , 建議DLL寫接口將 std::map 封裝起來,不曝露std::map給外部調用。DLL內使用STL類,需要做黑盒處理……

#15


可以啊,用啥都可以,但是要保证DLL调用的库(比如CB的库)被编译进DLL或随DLL发布

#1


dll最初是用c标准的,因此对容器,TForm等这些最好用activex来做更通用。

#2


因为我要写TCP通信程序,而我用了VCL里的TSocketClient这个组件,只能创建一个窗体并且做成dll才能被比如VC调用
引用 1 楼 songhtao 的回复:
dll最初是用c标准的,因此对容器,TForm等这些最好用activex来做更通用。

#3


好吧,因为没人回答,所以我尝试用别的方法。
现在我不在接口传递容器了,改用所有对容器的操作都在dll里实现

但又有新的问题,我在dll里定义了一个vector并push_back了一些数据,这个循环结束之后我立即打印出这些数据,但是。。。。。

还是打印乱码?这个貌似是内存管理出了问题,可是。。。我不知道怎么解决????

#4


没人啊。。。。

#5


如果在接口里直接传递STL容器,会发生问题,因为很多STL容器含有静态成员,APP和DLL的内存空间又不一样

在dll里定义了一个vector并push_back了一些数据,这个循环结束之后我立即打印出这些数据
请贴代码

#6


我找到了,我用map容器insert了指针,但是之后立刻删除了,所以会出错。但是现在还有点问题。我大概写下代码
 

whie(getline(infile, ss))
{
    string s1 = ss.substr(...);//...省略了
    string s2 = ss.substr(...);
    map<string, string> map1;
    map1.insert(make_pair(s1, s2));
}
char* str;
map<string, string>::iterator iter = map1.find(str);
if(iter != map1.end())
{
    ...
}

现在的问题是当str = NULL时,会出现异常,如果不为空则可以;这是为什么呢?

引用 5 楼 hind24 的回复:
如果在接口里直接传递STL容器,会发生问题,因为很多STL容器含有静态成员,APP和DLL的内存空间又不一样

在dll里定义了一个vector并push_back了一些数据,这个循环结束之后我立即打印出这些数据
请贴代码

#7


whie(getline(infile, ss)) 

{
  string s1 = ss.substr(...);//...省略了
  string s2 = ss.substr(...);
  map<string, string> map1;
  map1.insert(make_pair(s1, s2));
}
char* str;
map<string, string>::iterator iter = map1.find(str);
if(iter != map1.end())
{
  ...
}

#8


[code=C/C++][whie(getline(infile, ss))
{
  string s1 = ss.substr(...);//...省略了
  string s2 = ss.substr(...);
  map<string, string> map1;
  map1.insert(make_pair(s1, s2));
}
char* str;
map<string, string>::iterator iter = map1.find(str);
if(iter != map1.end())
{
  ...
}]

抱歉,竟然不会插入代码。。。。

#9


BCB6的 std::map 與 VC的std::map , 不同編譯器其STL類的內存布局可能不一樣,這就是DLL中不傳遞STL實例的一個內在原因。

另外,DLL與調用程序使用不同的內存空間,也使得STL類(map vector)的操作要十分小心,不小心就搞壞了內存。

一般不攷慮在DLL接口中傳遞STL類。除非用同一個編譯器。

#10


该回复于2012-03-03 09:49:01被版主删除

#11


但都是设计到字符串,而且还有一一对应的关系,如果不用STL用什么啊 char**?
引用 9 楼 ppower 的回复:
BCB6的 std::map 與 VC的std::map , 不同編譯器其STL類的內存布局可能不一樣,這就是DLL中不傳遞STL實例的一個內在原因。

另外,DLL與調用程序使用不同的內存空間,也使得STL類(map vector)的操作要十分小心,不小心就搞壞了內存。

一般不攷慮在DLL接口中傳遞STL類。除非用同一個編譯器。

#12


whie(getline(infile, ss))
{
  string s1 = ss.substr(...);//...省略了
  string s2 = ss.substr(...);
  map<string, string> map1;
  map1.insert(make_pair(s1, s2));
}
char* str = NULL;
map<string, string>::iterator iter = map1.find(str);//有人说str不能为NULL,为什么啊
if(iter != map1.end())
{
  ...
}

#13


1、有人说str不能为NULL,为什么啊
std::string 構造或賦值,不接受 NULL 指針 可以使用 "" ,但不能用 NULL ;

2、但都是设计到字符串,而且还有一一对应的关系,如果不用STL用什么啊 char**?
如果內部要使用 std::map , 建議DLL寫接口將 std::map 封裝起來,不曝露std::map給外部調用。DLL內使用STL類,需要做黑盒處理,也就是DLL接口中看不見STL模板類。
如果非得將 std::map 曝露出來,那麼你得將 std::map 的頭文件同樣發佈,這就相當於要求別人與你用同樣的 STL 庫版本,而且還得檢查編譯選項,以保障內存佈局一致,函數調用方式一樣。或者你重寫一個可供共用的 std::map 類。

#14


哦,谢谢了。我按照你说的做了,现在可以运行。内部使用STL还是可以的。。

先结贴了。

不过还有另外一个思考,希望还能回答一下哈。

既然内部使用STL可以,那内部使用C++Builder的AnsiString类型行不行呢,而且dll要被VC调用,而且VC那边没有装BCB
谢谢
引用 13 楼 ppower 的回复:
1、有人说str不能为NULL,为什么啊
std::string 構造或賦值,不接受 NULL 指針 可以使用 "" ,但不能用 NULL ;

2、但都是设计到字符串,而且还有一一对应的关系,如果不用STL用什么啊 char**?
如果內部要使用 std::map , 建議DLL寫接口將 std::map 封裝起來,不曝露std::map給外部調用。DLL內使用STL類,需要做黑盒處理……

#15


可以啊,用啥都可以,但是要保证DLL调用的库(比如CB的库)被编译进DLL或随DLL发布