怎样在DLL导出一个struct?

wendysen 2009-07-26 11:18:00
问题是这样。有一个DDL1,现在自己又做了一个DLL2,DLL中引用了DLL1的一个struct strXXXX。
在DLLCall中调用DLL2的函数以及类和结构,用到了结构strXXXX
那么请问,在DLL2中strXXXX应该怎么定义(引用)?如何导出呢?
...全文
1305 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
jufengaihaozhe 2009-07-29
  • 打赏
  • 举报
回复
DLL导出类
类和结构体大体相同

DLL中定义的类可以在应用工程中使用。

下面的例子里,我们在DLL中定义了point和circle两个类,并在应用工程中引用了它们(单击此处下载本工程)。

//文件名:point.h,point类的声明

#ifndef POINT_H

#define POINT_H

#ifdef DLL_FILE

class _declspec(dllexport) point //导出类point

#else

class _declspec(dllimport) point //导入类point

#endif

{

public:

float y;

float x;

point();

point(float x_coordinate, float y_coordinate);

};

#endif

//文件名:point.cpp,point类的实现

#ifndef DLL_FILE

#define DLL_FILE

#endif

#include "point.h"

//类point的缺省构造函数

point::point()

{

x = 0.0;

y = 0.0;

}

//类point的构造函数

point::point(float x_coordinate, float y_coordinate)

{

x = x_coordinate;

y = y_coordinate;

}

//文件名:circle.h,circle类的声明

#ifndef CIRCLE_H

#define CIRCLE_H

#include "point.h"

#ifdef DLL_FILE

class _declspec(dllexport)circle //导出类circle

#else

class _declspec(dllimport)circle //导入类circle

#endif

{

public:

void SetCentre(const point ¢rePoint);

void SetRadius(float r);

float GetGirth();

float GetArea();

circle();

private:

float radius;

point centre;

};

#endif

//文件名:circle.cpp,circle类的实现

#ifndef DLL_FILE

#define DLL_FILE

#endif

#include "circle.h"

#define PI 3.1415926

//circle类的构造函数

circle::circle()

{

centre = point(0, 0);

radius = 0;

}

//得到圆的面积

float circle::GetArea()

{

return PI *radius * radius;

}

//得到圆的周长

float circle::GetGirth()

{

return 2 *PI * radius;

}

//设置圆心坐标

void circle::SetCentre(const point ¢rePoint)

{

centre = centrePoint;

}

//设置圆的半径

void circle::SetRadius(float r)

{

radius = r;

}

类的引用:

#include "..\circle.h"//包含类声明头文件

#pragma comment(lib,"dllTest.lib");

int main(int argc, char *argv[])

{

circle c;

point p(2.0, 2.0);

c.SetCentre(p);

c.SetRadius(1.0);

printf("area:%f girth:%f", c.GetArea(), c.GetGirth());

return 0;

}

从上述源代码可以看出,由于在DLL的类实现代码中定义了宏DLL_FILE,故在DLL的实现中所包含的类声明实际上为:

class _declspec(dllexport) point //导出类point

{



}



class _declspec(dllexport) circle //导出类circle

{



}

而在应用工程中没有定义DLL_FILE,故其包含point.h和circle.h后引入的类声明为:

class _declspec(dllimport) point //导入类point

{



}



class _declspec(dllimport) circle //导入类circle

{



}

不错,正是通过DLL中的

class _declspec(dllexport) class_name //导出类circle

{



}

与应用程序中的

class _declspec(dllimport) class_name //导入类

{



}

匹对来完成类的导出和导入的!

我们往往通过在类的声明头文件中用一个宏来决定使其编译为class _declspec(dllexport) class_name还是class _declspec(dllimport) class_name版本,这样就不再需要两个头文件。本程序中使用的是:

#ifdef DLL_FILE

class _declspec(dllexport) class_name //导出类

#else

class _declspec(dllimport) class_name //导入类

#endif

实际上,在MFC DLL的讲解中,您将看到比这更简便的方法,而此处仅仅是为了说明_declspec(dllexport)与_declspec(dllimport)匹对的问题。

由此可见,应用工程中几乎可以看到DLL中的一切,包括函数、变量以及类,这就是DLL所要提供的强大能力。只要DLL释放这些接口,应用程序使用它就将如同使用本工程中的程序一样!
wendysen 2009-07-27
  • 打赏
  • 举报
回复
谢谢楼上的,好像是你说的那样哦,就是DLL2.h也得包含DLL1.h。
目前还没有发现其他问题,呵呵,多谢。
wendysen 2009-07-26
  • 打赏
  • 举报
回复
困难就是,我的strXXXX这个结构是在DLL1中定义的,我的DLL2重新封装了DLL1的函数,可是结构不知道怎么封装?
所以在DLLCall中包含DLL2.h和DLL2。lib时,因为用到了DLL1中的结构,就出错,不知道该怎么在DLL2中重新封装DLL1中的结构和导出!
arong1234 2009-07-26
  • 打赏
  • 举报
回复
你遇到什么错误了?

[Quote=引用 4 楼 wendysen 的回复:]
引用 3 楼 arong1234 的回复:
如果你结构没有定义成员函数和静态变量,只要放在头文件让别人包含即可,不需要导出


楼上的大侠可以详细一点吗/

但我的DLL2中  #include "DLL1.h"了
那DLLCall中只是包涵了DLL2头文件和库,但是为什么不能用DLL1中的strxxxx??
[/Quote]
wendysen 2009-07-26
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 arong1234 的回复:]
如果你结构没有定义成员函数和静态变量,只要放在头文件让别人包含即可,不需要导出
[/Quote]

楼上的大侠可以详细一点吗/

但我的DLL2中 #include "DLL1.h"了
那DLLCall中只是包涵了DLL2头文件和库,但是为什么不能用DLL1中的strxxxx??
arong1234 2009-07-26
  • 打赏
  • 举报
回复
如果你结构没有定义成员函数和静态变量,只要放在头文件让别人包含即可,不需要导出
oyljerry 2009-07-26
  • 打赏
  • 举报
回复
定义结构体,然后DLL中导出对应的方法get()等,然后把结构体作为get的参数等来传递对应的数据,你DLL中来获取。
可以把结构体放到一个公用的h文件中,所有的dll都可以引用它的定义
biweilun 2009-07-26
  • 打赏
  • 举报
回复
用接口导出,放出一些方法做接口调用
arong1234 2009-07-26
  • 打赏
  • 举报
回复
问题不在于dll2.cpp,而在于dll2.h
使用你dll2的人,一定会包含dll2.h吧?而dll2.h中引用了那个结构。在dll2中,由于你在dll2.cpp包含了dll1.h,因此不会出问题。而在使用dll2的exe工程中,你没有包含dll1.h,但是dll2.h又使用了dll1.h的结构,这个结构当然就成了未定义结构。所以你需要把dll2.h中所有对dll1中的类型的引用,才能不带dll1.h使用
[Quote=引用 17 楼 wendysen 的回复:]

我的DLL2.cpp中包含了DLL1.h,编译通过.
DLLCall工程中,如果不包含DLL1.h就报错,如果包含了DLL1.h就可以通过。

[/Quote]
wendysen 2009-07-26
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 arong1234 的回复:]
你说的非常不清楚!!你遇到的问题是“结构没有定义”,那么你就应该强调结构没有定义这个错误信息,但是你一直在问怎么导出结构,但是这个结构是不需要导出的,你的问题在严重误导别人。关注自己直接的问题,而不是漫无天际的创造一些问题来问。你应该直接贴出错误信息来询问,而不是在自己理解基础上问问题。如果你理解没有问题,恐怕就不需要问问题了。在一个有问题的理解的基础上问问题,很可能问的问题本身就完全错误。

C++是一个需要预先定义类型才能使用的语言,无论你逻辑上是怎么包装dll1的,只要你的dll2的头文件中引用了dll1定义的类型,但是你在dll2.h中没有定义dll1中的类型,并且也没有包含dll1.h,那当然要报类型找不到错误。

如果你完全不想把dll1.dll中的结构暴露给别人,你就需要确保你dll2的头文件中没有任何地方引用这个结构,否则要么你在dll2的头文件中重定义这个结构,要么包含dll1.h,这是显而易见的:引用的东西必须被定义

[/Quote]

我的DLL2.cpp中包含了DLL1.h,编译通过.
DLLCall工程中,如果不包含DLL1.h就报错,如果包含了DLL1.h就可以通过。

但是我并不理解为什么?

arong1234(阿荣)
还是要感谢你的批评!
IORI915189 2009-07-26
  • 打赏
  • 举报
回复
基础问题

自己用 自己定义的结构 自己还不清楚??
别人用 把结构定义给他 让他自己传递结构指针


arong1234 2009-07-26
  • 打赏
  • 举报
回复
我估计他不想把dll1的信息暴露给别人,这样他应该把dll2的头文件中所有和dll1有关的信息删除放到其他头文件中,而不是把dll1的信息放在他dll2头文件中,然后又不原意重定义dll1的类型,也不原意包含dll1的头文件。实际他还是不懂头文件的用处
[Quote=引用 13 楼 lsupper 的回复:]
不用导出啊,你定义个一样的就OK了~~~

或者你生成DLL的时候,的头文件拉过来就可以了~~~~
[/Quote]
arong1234 2009-07-26
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 wendysen 的回复:]

唉, 上帝啊,不知道我说清楚没有。
[/Quote]
表述的人有义务让别人清楚自己的想法,坚持“我其实说的很清楚,其实是因为你水你傻才不懂”是没有意义的,很显然,即使你在喊上帝的时候,你的表述还是错误的,你还在问“怎么导出”
lsupper 2009-07-26
  • 打赏
  • 举报
回复
不用导出啊,你定义个一样的就OK了~~~

或者你生成DLL的时候,的头文件拉过来就可以了~~~~
arong1234 2009-07-26
  • 打赏
  • 举报
回复
你说的非常不清楚!!你遇到的问题是“结构没有定义”,那么你就应该强调结构没有定义这个错误信息,但是你一直在问怎么导出结构,但是这个结构是不需要导出的,你的问题在严重误导别人。关注自己直接的问题,而不是漫无天际的创造一些问题来问。你应该直接贴出错误信息来询问,而不是在自己理解基础上问问题。如果你理解没有问题,恐怕就不需要问问题了。在一个有问题的理解的基础上问问题,很可能问的问题本身就完全错误。

C++是一个需要预先定义类型才能使用的语言,无论你逻辑上是怎么包装dll1的,只要你的dll2的头文件中引用了dll1定义的类型,但是你在dll2.h中没有定义dll1中的类型,并且也没有包含dll1.h,那当然要报类型找不到错误。

如果你完全不想把dll1.dll中的结构暴露给别人,你就需要确保你dll2的头文件中没有任何地方引用这个结构,否则要么你在dll2的头文件中重定义这个结构,要么包含dll1.h,这是显而易见的:引用的东西必须被定义

[Quote=引用 10 楼 wendysen 的回复:]
我不是说了吗,错误就是“一些结构没有定义”
我不知道在哪里定义,怎么导出。
不过刚刚试了下,在DLLCall中,加入#include "DLL1.h"  居然不再报错,可我DLLCall使用的是DLL2,所以很不理解。
唉, 上帝啊,不知道我说清楚没有。
[/Quote]
wendysen 2009-07-26
  • 打赏
  • 举报
回复
再重申一下,我的DLL2完全是重新封装DLL1,就是DLL1中的结构不知道怎么处理(怎么封装怎么导出)?
我在一个工程师用DLL2的时候,用到了DLL1的结构,但DLL2中并没有做任何处理,可是加上了 #include "DLL1.h",就不再出现“结构没有定义”的错误了。
这样表述可明白呢?
wendysen 2009-07-26
  • 打赏
  • 举报
回复
我不是说了吗,错误就是“一些结构没有定义”
我不知道在哪里定义,怎么导出。
不过刚刚试了下,在DLLCall中,加入#include "DLL1.h" 居然不再报错,可我DLLCall使用的是DLL2,所以很不理解。
唉, 上帝啊,不知道我说清楚没有。
arong1234 2009-07-26
  • 打赏
  • 举报
回复
不正确表述你的问题,不回应别人问你的,只坚持不断问你的问题是不可能得到答案的。要学会和别人交流
[Quote=引用 6 楼 wendysen 的回复:]
困难就是,我的strXXXX这个结构是在DLL1中定义的,我的DLL2重新封装了DLL1的函数,可是结构不知道怎么封装?
所以在DLLCall中包含DLL2.h和DLL2。lib时,因为用到了DLL1中的结构,就出错,不知道该怎么在DLL2中重新封装DLL1中的结构和导出!
[/Quote]
arong1234 2009-07-26
  • 打赏
  • 举报
回复
你到底有没有定义结构的成员函数或者静态变量?!
你的错误到底是什么?
[Quote=引用 6 楼 wendysen 的回复:]
困难就是,我的strXXXX这个结构是在DLL1中定义的,我的DLL2重新封装了DLL1的函数,可是结构不知道怎么封装?
所以在DLLCall中包含DLL2.h和DLL2。lib时,因为用到了DLL1中的结构,就出错,不知道该怎么在DLL2中重新封装DLL1中的结构和导出!
[/Quote]
一 组件基础 1 软件开发的阶段 1.1 结构化编程 采用自顶向下的编程方式,划分模块 和功能的一种编程方式。 1.2 面向对象编程 采用对象的方式,将程序抽象成类, 模拟现实世界,采用继承、多态的方式 设计软件的一种编程方式。 1.3 面向组件编程 将功能和数据封装成二进制代码,采用 搭积木的方式实现软件的一种编程方式。 2 组件和优点 2.1 组件 - 实际是一些可以执行的二进 制程序,它可以给其他的应用程序、操 作系统或其他组件提供功能 2.2 优点 2.2.1 可以方便的提供软件定制机制 2.2.2 可以很灵活的提供功能 2.2.3 可以很方便的实现程序的分布式 开发。 3 组件的标准 - COM(Component Object Model ) 3.1 COM是一种编程规范,不论任何开发语言 要实现组件都必须按照这种规范来实现。 组件和开发语言无关。 这些编程规范定义了组件的操作、接口的 访问等等。 3.2 COM接口 COM接口是组件的核心,从一定程度上 讲"COM接口是组件的一切". COM接口给用户提供了访问组件的方式. 通过COM接口提供的函数,可以使用组件 的功能. 4 COM组件 4.1 COM组件-就是在Windows平台下, 封装在动态库(DLL)或者可执行文件(EXE) 中的一段代码,这些代码是按照COM的 规范实现. 4.2 COM组件的特点 4.2.1 动态链接 4.2.2 与编程语言无关 4.2.3 以二进制方式发布 二 COM接口 1 接口的理解 DLL的接口 - DLL导出的函数 类的接口 - 类的成员函数 COM接口 - 是一个包含了一组函数指针 的数据结构,这些函数是由组件实现的 2 C++的接口实现 2.1 C++实现接口的方式,使用抽象类 定义接口. 2.2 基于抽象类,派生出子类并实现 功能. 2.3 使用 interface 定义接口 interface ClassA { }; 目前VC中,interface其实就是struct 3 接口的动态导出 3.1 DLL的实现 3.1.1 接口的的定义 3.1.2 接口的实现 3.1.3 创建接口的函数 3.2 DLL的使用 3.2.1 加载DLL和获取创建接口的函数 3.2.2 创建接口 3.2.3 使用接口的函数 4 接口的生命期 4.1 问题 在DLL中使用new创建接口后,在用户 程序使用完该接口后,如果使用delete 直接删除,会出现内存异常. 每个模块有自己的内存堆(crtheap) EXE - crtheap DLL - crtheap new/delete/malloc/free默认情况 下都是从自己所在模块内存堆(crtheap) 中分配和施放内存.而各个模块的 这个内存堆是各自独立.所以在DLL中 使用new分配内存,不能在EXE中delete. 4.2 引用计数和AddRef/Release函数 引用计数 - 就是一个整数,作用是 表示接口的使用次数 AddRef - 增加引用计数 +1 Release - 减少引用计数 -1, 如果 当引用计数为0,接口被删除 4.3 使用 4.3.1 创建接口 4.3.2 调用AddRef,增加引用计数 4.3.3 使用接口 4.3.4 调用Release,减少引用计数 4.4 注意 4.4.1 在调用Release之后,接口指针 不能再使用 4.4.2 多线程情况下,接口引用计数 要使用原子锁的方式进行加减 5 接口的查询 5.1 每个接口都具有唯一标识 GUID 5.2 实现接口查询函数 QueryInterface 6 IUnknown 接口 6.1 IUnknown是微软定义的标准接口 我们实现所有接口就是继承这个接口 6.2 IUnknown定义了三个函数 QueryInterface 接口查询函数 AddRef 增加引用计数 Release 减少引用计数 7 接口定义语言 - IDL(Interface Definition Language ) 7.1 IDL和MIDL IDL - 定义接口的一种语言,与开发 语言无关. MIDL.EXE - 可以将IDL语言定义接口, 编译成C++语言的接口定义 7.2 IDL的基础 import "XXXX.idl" [ attribute ] interface A : interface_base { } 7.2.1 Import 导入,相当于C++的 #include 7.2.2 使用"[]"定义区域,属性描述 关键字 1) object - 后续是对象 2) uuid - 定义对象GUID 3) helpstring - 帮助信息 4) version - 版本 5) point_default - 后续对象 中指针的默认使用方式 比如: uniqune - 表示指针可以 为空,但是不能修改 7.2.3 对象定义 1) 父接口是IUnknown接口 2) 在对象内添加函数,函数定义必须 是返回 HRESULT. HRESULT是32位整数,返回函数是否 执行成功,需要使用 SUCCESSED和 FAILED宏来判断返回值.
Go语言性能好、语法简单、开发效率高!一起来探索Go 语言吧!本课程特别适合从事PHP/Python/Ruby/Node.js等Web开发的读者,通过本课程可以了解编译型语言怎么写Web应用开发,系统底层怎么进行网络通信。 beego 简介beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API、Web 及后端服务等各种应用,是一个 RESTful 的框架,主要设计灵感来源于 tornado、sinatra 和 flask 这三个框架,但是结合了 Go 本身的一些特性(interface、struct 嵌入等)而设计的一个框架。beego 的架构beego 的整体设计架构如下所示:beego 是基于八大独立的模块构建的,是一个高度解耦的框架。当初设计 beego 的时候就是考虑功能模块化,用户即使不使用 beego 的 HTTP 逻辑,也依旧可以使用这些独立模块,例如:你可以使用 cache 模块来做你的缓存逻辑;使用日志模块来记录你的操作信息;使用 config 模块来解析你各种格式的文件。所以 beego 不仅可以用于 HTTP 类的应用开发,在你的 socket 游戏开发中也是很有用的模块,这也是 beego 为什么受欢迎的一个原因。大家如果玩过乐高的话,应该知道很多高级的东西都是一块一块的积木搭建出来的,而设计 beego 的时候,这些模块就是积木,高级机器人就是 beego。至于这些模块的功能以及如何使用会在后面的文档逐一介绍。beego 的执行逻辑既然 beego 是基于这些模块构建的,那么它的执行逻辑是怎么样的呢?beego 是一个典型的 MVC 架构,它的执行逻辑如下图所示:beego 项目结构一般的 beego 项目的目录如下所示:├── conf│   └── app.conf├── controllers│   ├── admin│   └── default.go├── main.go├── models│   └── models.go├── static│   ├── css│   ├── ico│   ├── img│   └── js└── views    ├── admin    └── index.tpl从上面的目录结构我们可以看出来 M(models 目录)、V(views 目录)和 C(controllers 目录)的结构, main.go 是入口文件。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧