C语言:如何自己做库函数?简单的一个例子,但是基本的程序编译的思想都在里面了,具体的需要你自己体会和查资料
跟着下面的步骤走
------------------------
第一步:我的电脑-属性-高级-环境变量
添加3个变量
1.名字:path 值:vc的安装目录里面包含cl.exe的bin目录路径 ";" vc目录下包含mspdb80.dll的目录的路径
比如我的是D:\Program Files\Microsoft Visual Studio 8\VC\bin;D:\Program Files\Microsoft Visual Studio 8\Common7\IDE;
2.名字:include 值:vc安装目录下的include目录,主要是为了找到头文件,我的是D:\Program Files\Microsoft Visual Studio 8\VC\include;D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include;
3.名字:lib 值:vc目录下包含库文件的目录路径
我的是D:\Program Files\Microsoft Visual Studio 8\VC\lib;D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Lib;
第二步:需要下面两个文件
//-------------libdemo.c
#include stdio.h
void lib_func()
{
printf("this routine in lib\n");
}
//------------main.c
void lib_func();
int main(int argc, char *argv[])
{
lib_func();
}
第三步:命令
cl /c libdemo.c'编译libdemo.c 生成libdemo.obj
liblibdemo.obj'生成libdemo.lib 库文件
cl /c main.c'编译main.c
link main.objlibdemo.lib'生成main.exe
---------------------------------------------------
呵呵 加点东西,参看4楼的建议,在做个dll,COM组件就不做了,有点复杂了
1 。把libdemo.c 稍微改下
//-------------libdemo.c
#include stdio.h
__declspec (dllexport) void lib_func()
{
printf("this routine in lib\n");
}
2 。命令
cl /c libdemo.c main.c
link libdemo.obj /dll'生成libdemo.lib
link main.obj libdemo.lib
关于c语言中如何创建自己的库函数能不能再详细的解释一下,谢谢了?。。?/h2>哈哈,选我吧!库分静态库和动态链接库,静态库以lib结尾,被编译器里的链接器识别 。windows下动态库以dll结尾,被操作系统加载以模块方式映射到进程地址空间 。一般初学者先学会创建的是静态库 。静态库是一个无需重定位的函数集 。怎么做到无需重定位呢?这是编译器做的编译工作,例如它指定开头的位置作为基址,剩下的代码用到的都是相对偏移 。这样,这段二进制代码可以被放在内存中的任何位置执行,被写入了lib文件里 。在lib文件里 , 包含了函数名与函数地址组成的结构体,通过它编译器可以找到lib文件里需要的二进制代码并以静态联编的方式写入我们调用它的exe文件里 。这种代码是被塞进exe文件里而无需修改,并在程序执行时被用到 。为了让库被别人调用,我们可以写一个头文件.h,包含函数原型及声明 。
C语言库函数如何编写?/***
*printf.c - print formatted
*
* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines printf() - print formatted data
*
*******************************************************************************/
#include
#include
#include
#include
#include
#include
#include
/***
*int printf(format, ...) - print formatted data
*
*Purpose:
* Prints formatted data on stdout using the format string to
* format data and getting as many arguments as called for
* Uses temporary buffering to improve efficiency.
* _output does the real work here
*
*Entry:
* char *format - format string to control data format/number of arguments
* followed by list of arguments, number and type controlled by
* format string
*
*Exit:
* returns number of characters printed
*
*Exceptions:
*
*******************************************************************************/
int __cdecl printf (
const char *format,
...
)
/*
* stdout ''PRINT'', ''F''ormatted
*/
{
va_list arglist;
int buffing;
int retval;
va_start(arglist, format);
_ASSERTE(format != NULL);//断言宏 。如果输出格式字符串指针为空,则在DEBUG版下断言,报告错误 。
_lock_str2(1, stdout);
buffing = _stbuf(stdout);//stdout:指定输出到屏幕
retval = _output(stdout,format,arglist);
_ftbuf(buffing, stdout);
_unlock_str2(1, stdout);
return(retval);
}
以上为printf()的源代码
1、从含有可选参数函数中获得可选参数 , 以及操作这些参数
typedef char *va_list;
void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
假定函数含有一个必选参数和多个可选参数 , 必选参数声明为普通数据类型 , 且能通过参数名来获得该变量的值 。可选参数通过宏va_start、va_arg和va_end(定义在stdarg.h或varargs.h中)来进行操作,即通过设置指向第一个可选参数指针、返回当前参数、在返回参数后重新设置指针来操作所有的可选参数 。
va_start:为获取可变数目参数的函数的参数提供一种便捷手段 。设置arg_ptr为指向传给函数参数列表中的第一个可选参数的指针,且该参数必须是va_list类型 。prev_param是在参数列表中第一个可选参数前的必选参数 。
va_arg:返回由arg_ptr所指向的参数的值,且自增指向下一个参数的地址 。type为当前参数的类型,用来计算该参数的长度,确定下一个参数的起始位置 。它可以在函数中应用多次,直到得到函数的所有参数为止 , 但必须在宏va_start后面调用 。
va_end:在获取所有的参数后,设置指针arg_ptr为NULL 。
下面举例说明:
#include
#include
int average( int first, ... );
void main( void )
{
/* Call with 3 integers (-1 is used as terminator). */
printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );
/* Call with 4 integers. */
printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );
/* Call with just -1 terminator. */
printf( "Average is: %d\n", average( -1 ) );
}
int average( int first, ... )
{
int count = 0, sum = 0, i = first;
va_list marker;
va_start( marker, first ); /* Initialize variable arguments. */
while( i != -1 )
{
sum= i;
count;
i = va_arg( marker, int);
}
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}
返回值为:
Average is: 3
Average is: 8
Average is: 0
综上所述,在printf()函数中,可以只输出一个字符串,也可按照一定的形式输出含有多个可选参数的字符串信息 。因此 , 首先就要通过这些宏来获取所有的可选参数 。在上面的源码可以看出printf()中,只使用了宏at_start,将可选参数的首地址赋给了arglist 。
2、锁定字符串及输出字符串到屏幕
#define _lock_str2(i,s) _lock_file2(i,s)
void __cdecl _lock_file2(int, void *);
#define _unlock_str2(i,s) _unlock_file2(i,s)
void __cdecl _unlock_file2(int, void *);
int __cdecl _stbuf(FILE *);
void __cdecl _ftbuf(int, FILE *);
int __cdecl _output(FILE *, const char *, va_list);
在output函数中,读取格式字符串中的每一个字符,然后对其进行处理,处理方式根据每一个字符所代表的意义来进行,如:普通字符直接利用函数WRITE_CHAR(ch, charsout);输出到控制台 。
其中的主要部分是对转换说明符(d,c,s,f)的处理,现在将对其中的部分代码进行详细说明,这里只说明最基本的转换说明符,对这些须基本的转换说明符进行修饰的修饰符,程序中单独进行处理 。下面是函数output()(output.c)部分源代码:
case ST_TYPE:
//表示当前处理的字符的类型为转换说明符 。
...
switch (ch) {
//下面对参数的获取都是利用宏va_arg( va_list arg_ptr, type );来进行的 。
case ''c'': {
//从参数表中获取单个字符 , 输出到缓冲字符串中,此时,type=int
buffer[0] = (char) get_int_arg(argptr); /* get char to print */
text = buffer;
textlen = 1; /* print just a single character */
}
break;
case ''s'': {
//从参数表中获取字符串,输出到缓冲字符串中,此时,type=char*
int i;
char *p; /* temps */
text = get_ptr_arg(argptr);
...
}
break;
case ''w'': {
//对宽字符进行处理
...
} /* case ''w'' */
break;
...
case ''e'':
case ''f'':
case ''g'': {
//对浮点数进行操作
...
#if !LONGDOUBLE_IS_DOUBLE
/* do the conversion */
if (flagsFL_LONGDOUBLE) {
_cldcvt((LONGDOUBLE*)argptr, text, ch, precision, capexp);
va_arg(argptr, LONGDOUBLE);
//对长双精度型进行处理,此时,type=long double
}
else
#endif /* !LONGDOUBLE_IS_DOUBLE */
{
//对双精度型进行处理,此时,type=double
_cfltcvt((DOUBLE*)argptr, text, ch, precision, capexp);
va_arg(argptr, DOUBLE);
}
...
break;
//对整型变量处理
case ''d'':
case ''i'':
...
goto COMMON_INT;
case ''u'':
radix = 10;
goto COMMON_INT;
case ''p'':
...
goto COMMON_INT;
case ''o'':
...
注:对于浮点型double和long double , 有相应的转换说明符(%f表示双精度型 , %lf表示长双精度型),而float却没有 。其中的原因是,在KRC下,float值用于表达式或用作参数前,会自动转换成double类型 。而ANSI C一般不会自动把float转换成double 。有些程序已假定其中的float参数会被转换成double,为了保护大量这样的程序 , 所有printf()函数的float参数还是被自动转换成double型 。因此,在KRC或ANSI C下,都无需用特定的转换说明符来显示float型 。
综上所述,转换说明符必须与待打印字符的类型 。通常,用户有种选择 。例如,如要打印一个int类型的值 。则只可以使用%d,%x或%o 。所有这些说明符都表示要打印一个int类型的值;它们只不过提供了一个数值的几种不同表示 。类似一,可以用%f、%g和%e来表示double类型的值 。但如果转换说明与类型不匹配,将会出现意想不到的结果 。为什么呢?问题就在于C向函数传递信息的方式 。
这个失败的根本细节与具体实现相关 。它决定了系统中的参数以何方式传递 。函数调用如下:
float n1;
double n2;
long n3;
long n4;
...
printf("%ld,%ld,%ld,%ld",n1,n2,n3,n4);
这个调用告诉计算机,要把变量n1,n2,n3和n4的值交给计算机,它把这些变量放进称作栈(stack)的内存区域中,来完成这一任务 。计算机把这些值放进栈中,其根据是变量的类型而不是转换说明符,比如n1,把8个字节放入栈中(float被转换成double),类似地,为n2放了8字节,其后给n3和n4各放了4个字节 。接着 , 控制的对象转移到printf();此函数从栈中读数,不过在这一过程中,它是在转换说明符的指导下 , 读取数值的 。说明符%ld指定printf()应读4个字节(va_arg( va_list arg_ptr, type )中type=long),因此printf()读入栈中的4个字节,作为它的第一个值 。但是这只是n1的前半部分,这个值被看成一个long整数 。下一个说明符%ld读入4个字节 , 这正是n1的后半部分,这个值被看成第二个long整数 。类似地 , 第三、第四次又读入n2的前后两部分 。因此,尽管我们对n3和n4使用了正确的说明符,printf()仍然会产生错误 。
怎么在c语言中自己写库函数1、不同的系统开发函数库的具体步骤是不一样的,这主要决定于编译、链接环境 。
2、不同的库开发方式也不一样 , 现在主流的库开发有两种,一种是静态库,一种是动态库,两者的本质区别是库代码是否和程序融合在一起,如果组装在一起就是静态库,如果不组装在一起,即为动态库 , 现在操作系统提供的多数是动态库,如Linux平台的.so文件,windows平台的DLL文件 。
3、以Windows平台为例 , 用户可以通过Vc/vs等IDE集成开发环境,生成DLL工程,然后编写def文件进行导出 。
C语言有没有自带画图函数库,该怎么应用?有,你可以使用graphics.h 头文件调用标准C函数
不过
16位c编译器绘图,就是中断调用
turboc的图形库就是封装了中断调用,不过支持的分辨率最高只有640*480
并不支持SVGA
支持SVGA的高分辨率绘图通过调用中断 10h的4f功能来实现
主要分辨率设置代码
unsigned char set_SVGA_mode(int vmode)
{union REGS r;
r.x.ax=0x4f02;
r.x.bx=vmode;
int86(0x10,r,r);
return(r.h.ah);
}
void hide_text_cursor(void)
{union REGS r;
r.h.ah=1;
r.h.ch=32;
int86(0x10,r,r);
}
void selectpage(register char page)
{union REGS r;
r.x.ax=0x4f05;
r.x.bx=0;
r.x.dx=page;
int86(0x10,r,r);
}
void show_text_cursor(char size)
{union REGS r;
r.h.ah=1;
r.h.cl=size;
r.h.ch=7;
int86(0x10,r,r);
}
unsigned int get_SVGA_mode()
{union REGS r;
r.x.ax=0x4f03;
int86(0x10,r,r);
return(r.x.bx);
}
这个在所有16位C编译器里都可以使用,只是略有不同
c语言的图形函数库有哪些图形和图像函数包含在graphics.h里面(一) 像素函数56. putpiel() 画像素点函数57. getpixel()返回像素色函数(二) 直线和线型函数58. line() 画线函数59. lineto() 画线函数60. linerel() 相对画线函数61. setlinestyle() 设置线型函数62. getlinesettings() 获取线型设置函数63. setwritemode() 设置画线模式函数(三)、多边形函数64. rectangle() 画矩形函数65. bar() 画条函数66. bar3d() 画条块函数67. drawpoly() 画多边形函数(四)、 圆、弧和曲线函数68. getaspectratio()获取纵横比函数69. circle()画圆函数70. arc() 画圆弧函数71. ellipse()画椭圆弧函数72. fillellipse() 画椭圆区函数73. pieslice() 画扇区函数74. sector() 画椭圆扇区函数75. getarccoords()获取圆弧坐标函数(五)、 填充函数76. setfillstyle() 设置填充图样和颜色函数77. setfillpattern() 设置用户图样函数78. floodfill() 填充闭域函数79. fillpoly() 填充多边形函数80. getfillsettings() 获取填充设置函数81. getfillpattern() 获取用户图样设置函数(六)、图像函数82. imagesize() 图像存储大小函数83. getimage() 保存图像函数84. putimage() 输出图像函数四、图形和图像函数对许多图形应用程序c语言绘制函数库,直线和曲线是非常有用c语言绘制函数库的 。但对有些图形只能靠操作单个像素才能画出 。当然如果没有画像素的功能 , 就无法操作直线和曲线的函数 。而且通过大规模使用像素功能,整个图形就可以保存、写、擦除和与屏幕上的原有图形进行叠加 。(一) 像素函数56. putpixel() 画像素点函数功能: 函数putpixel() 在图形模式下屏幕上画一个像素点 。用法: 函数调用方式为void putpixel(int x,int y,int color);说明: 参数x,y为像素点的坐标,color是该像素点的颜色,它可以是颜色符号名 , 也可以是整型色彩值 。此函数相应的头文件是graphics.h返回值: 无例: 在屏幕上(6,8)处画一个红色像素点:putpixel(6,8,RED);57. getpixel()返回像素色函数功能: 函数getpixel()返回像素点颜色值 。用法: 该函数调用方式为int getpixel(int x,int y);说明: 参数x,y为像素点坐标 。函数的返回值可以不反映实际彩色值,这取决于调色板的设置情况(参见setpalette()函数) 。这个函数相应的头文件为graphics.h返回值: 返回一个像素点色彩值 。例: 把屏幕上(8,6)点的像素颜色值赋给变量color 。color=getpixel(8,6);
【c语言绘制函数库 c语言库函数的使用方法】关于c语言绘制函数库和c语言库函数的使用方法的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。
推荐阅读
- 日常linux命令,linux常用命令 知乎
- 什么电视上能出现演员表,什么电视上能出现演员表名字
- jquery整屏切换,jquery实现选项卡切换
- ios14.2更新什么,ios142更新时间要多久
- 火鸟数据库php连接 火鸟sql服务器
- 舞蹈拍摄有什么效果,拍摄舞蹈用什么镜头
- 路由器怎么解绑银行卡流程,银行卡解绑怎么操作
- thinkphp3.2add乱码,thinkphp codeigniter
- 怎么让mysql超时 mysql查询超时时间配置