Linux下基于Libmad库的MP3音乐播放器编写

简介:

  libmad是一个开源mp3解码库,其对mp3解码算法做了很多优化,性能较好,很多播放器如mplayer、xmms等都是使用这个开源库进行解码的;如果要设计mp3播放器而又不想研        究mp3解码算法的话,libmad是个不错的选择。关于该库的使用,叙述如下。


一:安装Libmad:

   1、在网上下载:Libmad库的使用.pdf文档和libmad-0.15.lb.tar.gz压缩包( http://down.51cto.com/data/1087041(免费下载))


   2、解压:tar -zxvf libmad-0.15.lb.tar.gz


   以下过程在Readme和INSTALL文件中列了出来,应学会自己看选项进行操作:


   3、cd libmad-0.15.lb


   4、./configure


   5、make


   6、make check


   7、make install

   (若最后有错误信息,说明你用的gcc版本太高,该版本的gcc有"-fforce-mem"参数,打开根目录下的Makefile去掉里面的"-fforce-mem"就OK了。)


   结果:产生一个 .libs 目录


--------------------------------------------------------------------------------------------------------------————————————————

然后按照Libmad库的使用.pdf文档中的提示继续往下进行。


二:查看示例代码 minimad.c:


   minimad.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
  * libmad - MPEG audio decoder library
  * Copyright (C) 2000-2004 Underbit Technologies, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * $Id: minimad.c,v 1.4 2004/01/23 09:41:32 rob Exp $
  */
# include <stdio.h>
# include <unistd.h>
# include <sys/stat.h>
# include <sys/mman.h>
# include "mad.h"
/*
  * This is perhaps the simplest example use of the MAD high-level API.
  * Standard input is mapped into memory via mmap(), then the high-level API
  * is invoked with three callbacks: input, output, and error. The output
  * callback converts MAD's high-resolution PCM samples to 16 bits, then
  * writes them to standard output in little-endian, stereo-interleaved
  * format.
  */
static  int  decode(unsigned  char  const  *, unsigned  long );
int  main( int  argc,  char  *argv[])
{
   struct  stat stat;
   void  *fdm;
   if  (argc != 1)
     return  1;
   if  (fstat(STDIN_FILENO, &stat) == -1 ||
       stat.st_size == 0)
     return  2;
   fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, STDIN_FILENO, 0);
   if  (fdm == MAP_FAILED)
     return  3;
   decode(fdm, stat.st_size);
   if  (munmap(fdm, stat.st_size) == -1)
     return  4;
   return  0;
}
/*
  * This is a private message structure. A generic pointer to this structure
  * is passed to each of the callback functions. Put here any data you need
  * to access from within the callbacks.
  */
struct  buffer {
   unsigned  char  const  *start;
   unsigned  long  length;
};
/*
  * This is the input callback. The purpose of this callback is to (re)fill
  * the stream buffer which is to be decoded. In this example, an entire file
  * has been mapped into memory, so we just call mad_stream_buffer() with the
  * address and length of the mapping. When this callback is called a second
  * time, we are finished decoding.
  */
static
enum  mad_flow input( void  *data,
             struct  mad_stream *stream)
{
   struct  buffer *buffer = data;
   if  (!buffer->length)
     return  MAD_FLOW_STOP;
   mad_stream_buffer(stream, buffer->start, buffer->length);
   buffer->length = 0;
   return  MAD_FLOW_CONTINUE;
}
/*
  * The following utility routine performs simple rounding, clipping, and
  * scaling of MAD's high-resolution samples down to 16 bits. It does not
  * perform any dithering or noise shaping, which would be recommended to
  * obtain any exceptional audio quality. It is therefore not recommended to
  * use this routine if high-quality output is desired.
  */
static  inline
signed  int  scale(mad_fixed_t sample)
{
   /* round */
   sample += (1L << (MAD_F_FRACBITS - 16));
   /* clip */
   if  (sample >= MAD_F_ONE)
     sample = MAD_F_ONE - 1;
   else  if  (sample < -MAD_F_ONE)
     sample = -MAD_F_ONE;
   /* quantize */
   return  sample >> (MAD_F_FRACBITS + 1 - 16);
}
/*
  * This is the output callback function. It is called after each frame of
  * MPEG audio data has been completely decoded. The purpose of this callback
  * is to output (or play) the decoded PCM audio.
  */
static
enum  mad_flow output( void  *data,
              struct  mad_header  const  *header,
              struct  mad_pcm *pcm)
{
   unsigned  int  nchannels, nsamples;
   mad_fixed_t  const  *left_ch, *right_ch;
   /* pcm->samplerate contains the sampling frequency */
   nchannels = pcm->channels;
   nsamples  = pcm->length;
   left_ch   = pcm->samples[0];
   right_ch  = pcm->samples[1];
   while  (nsamples--) {
     signed  int  sample;
     /* output sample(s) in 16-bit signed little-endian PCM */
     sample = scale(*left_ch++);
     putchar ((sample >> 0) & 0xff);
     putchar ((sample >> 8) & 0xff);
     if  (nchannels == 2) {
       sample = scale(*right_ch++);
       putchar ((sample >> 0) & 0xff);
       putchar ((sample >> 8) & 0xff);
     }
   }
   return  MAD_FLOW_CONTINUE;
}
/*
  * This is the error callback function. It is called whenever a decoding
  * error occurs. The error is indicated by stream->error; the list of
  * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h)
  * header file.
  */
static
enum  mad_flow error( void  *data,
             struct  mad_stream *stream,
             struct  mad_frame *frame)
{
   struct  buffer *buffer = data;
   fprintf (stderr,  "decoding error 0x%04x (%s) at byte offset %u\n" ,
       stream->error, mad_stream_errorstr(stream),
       stream->this_frame - buffer->start);
   /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */
   return  MAD_FLOW_CONTINUE;
}
/*
  * This is the function called by main() above to perform all the decoding.
  * It instantiates a decoder object and configures it with the input,
  * output, and error callback functions above. A single call to
  * mad_decoder_run() continues until a callback function returns
  * MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and
  * signal an error).
  */
static
int  decode(unsigned  char  const  *start, unsigned  long  length)
{
   struct  buffer buffer;
   struct  mad_decoder decoder;
   int  result;
   /* initialize our private message structure */
   buffer.start  = start;
   buffer.length = length;
   /* configure input, output, and error functions */
   mad_decoder_init(&decoder, &buffer,
            input, 0  /* header */ , 0  /* filter */ , output,
            error, 0  /* message */ );
   /* start decoding */
   result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
   /* release the decoder */
   mad_decoder_finish(&decoder);
   return  result;
}


   编译: gcc -o minimad minimad.c –lmad

   运行: ./minimad <test.mp3 >test.pcm



   以上是将:1、标准输入重定向到MP3文件

             2、标准输出重定向到解码以后的 pcm 文件

   下面将pcm数据写入音频设备(即pcmplay.c程序):

      ( A.设备文件/dev/dsp

B.ioctl设置音频属性:     (记得加<sys/soundcard.h>头文件)

a.采样格式

b.采样频率

c.声道

C.将pcm文件写入音频设备)

   文档中pcmplay.c程序中void writefully(int fd,void *buf,int size);函数未给出,下面已补全。


   pcmplay.c代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/soundcard.h>
void  writefully( int  fd, void  *buf, int  size)
{
         int  n = write(fd,buf,size);
         if (n < 0)
             {
                     fprintf (stderr, "writefully error!" , strerror ( errno ));
                     exit (-1);
             }
}
int  main( int  argc,  char  *argv[])
{
     int  handle, fd;
     char  buf[1024];
     if  (argc != 2)
     {
         fprintf (stderr,  "usage : %s \n" , argv[0]);
         exit (-1);
     }
     if  ((fd = open(argv[1], O_RDONLY)) < 0)
     {
         fprintf (stderr,  "Can't open sound file!\n" );
         exit (-2);
     }
     if  ((handle = open( "/dev/dsp" , O_WRONLY))<0)
     {
         fprintf (stderr,  "Can't open system file /dev/dsp!\n" );
         exit (-2);
     }
     #if 1
     //设置声道
     int  channels = 2;
     int  result = ioctl(handle, SNDCTL_DSP_CHANNELS, &channels);
     if  ( result == -1 )
     {
         perror ( "ioctl channel number" );
         return  -1;
     }
     //设置采样格式:AFMT_S16_LE
     int  format = AFMT_S16_LE;
     result = ioctl(handle, SNDCTL_DSP_SETFMT, &format);
     if  ( result == -1 )
     {
         perror ( "ioctl sample format" );
         return  -1;
     }
     //设置采样频率44.1
     //int rate = 22050;
     int  rate = 44100;
     result = ioctl(handle, SNDCTL_DSP_SPEED, &rate);
     if  ( result == -1 )
     {
         perror ( "ioctl sample format" );
         return  -1;
     }
     #endif
     int  n;
     while ((n=read(fd,buf, sizeof (buf))))
     {
         writefully(handle,buf,n);
     }
     close(fd);
     close(handle);
     exit (0);
}

   编译: gcc -o pcmplay pcmplay.c

   运行: ./pcmplay test.pcm


   如此即可先将.mp3文件整个解压到.pcm文件中,再通过将.pcm文件写入音频设备进行.mp3音乐播放。

   下面简易实现.mp3音乐文件的编解码边播放程序的编写。



------------------------------------------------------------------------------------------------—————————————————————

三:编解码边播放,用Libmad设计一个简单的MP3播放器:


  “Libmad库的使用.pdf”文档中MP3player.c程序有些许缺失或错误,现已改正,程序如下:


   MP3player.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#include "mad.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#define BUFSIZE 8192
/*
* This is a private message structure. A generic pointer to this structure
* is passed to each of the callback functions. Put here any data you need
* to access from within the callbacks.
*/  
struct  buffer {
     FILE  *fp;  /*file pointer*/
     unsigned  int  flen;  /*file length*/
     unsigned  int  fpos;  /*current position*/
     unsigned  char  fbuf[BUFSIZE];  /*buffer*/
     unsigned  int  fbsize;  /*indeed size of buffer*/
};
typedef  struct  buffer mp3_file;
int  soundfd;  /*soundcard file*/
unsigned  int  prerate = 0;  /*the pre simple rate*/
int  writedsp( int  c)
{
     return  write(soundfd, ( char  *)&c, 1);
}
void  set_dsp()
{
     int  rate = 44100;
//  int rate = 96000;
   int  format = AFMT_S16_LE;
     int  channels = 2;
     int  value;
     soundfd = open( "/dev/dsp" , O_WRONLY);
                                                                                                                                                                                                                                                                                                                                                                                                             
     ioctl(soundfd,SNDCTL_DSP_SPEED,&rate);
     ioctl(soundfd, SNDCTL_DSP_SETFMT, &format);
     ioctl(soundfd, SNDCTL_DSP_CHANNELS, &channels);
/*
     value = 16;
     ioctl(soundfd,SNDCTL_DSP_SAMPLESIZE,&value);
     value = 0;
     ioctl(soundfd,SNDCTL_DSP_STEREO,&value);
*/
}
/*
* This is perhaps the simplest example use of the MAD high-level API.
* Standard input is mapped into memory via mmap(), then the high-level API
* is invoked with three callbacks: input, output, and error. The output
* callback converts MAD's high-resolution PCM samples to 16 bits, then
* writes them to standard output in little-endian, stereo-interleaved
* format.
*/
static  int  decode(mp3_file *mp3fp);
int  main( int  argc,  char  *argv[])
{
     long  flen, fsta, fend;
     int  dlen;
     mp3_file *mp3fp;
     if  (argc != 2)
     return  1;
     mp3fp = (mp3_file *) malloc ( sizeof (mp3_file));
     if ((mp3fp->fp =  fopen (argv[1],  "r" )) == NULL)
     {
         printf ( "can't open source file.\n" );
         return  2;
     }
     fsta =  ftell (mp3fp->fp);
     fseek (mp3fp->fp, 0, SEEK_END);
     fend =  ftell (mp3fp->fp);
     flen = fend - fsta;
     fseek (mp3fp->fp, 0, SEEK_SET);
     fread (mp3fp->fbuf, 1, BUFSIZE, mp3fp->fp);
     mp3fp->fbsize = BUFSIZE;
     mp3fp->fpos = BUFSIZE;
     mp3fp->flen = flen;
     set_dsp();
     decode(mp3fp);
     close(soundfd);
     fclose (mp3fp->fp);
     return  0;
}
/*
* This is the input callback. The purpose of this callback is to (re)fill
* the stream buffer which is to be decoded. In this example, an entire file
* has been mapped into memory, so we just call mad_stream_buffer() with the
* address and length of the mapping. When this callback is called a second
* time, we are finished decoding.
*/
static
enum  mad_flow input( void  *data,
struct  mad_stream *stream)
{
     mp3_file *mp3fp;
     int  ret_code;
     int  unproc_data_size;  /*the unprocessed data's size*/
     int  copy_size;
     mp3fp = (mp3_file *)data;
     if (mp3fp->fpos <= mp3fp->flen)
     {
         unproc_data_size = stream->bufend - stream->next_frame;
         memcpy (mp3fp->fbuf, mp3fp->fbuf+mp3fp->fbsize-unproc_data_size, unproc_data_size);
         copy_size = BUFSIZE - unproc_data_size;
         if (mp3fp->fpos + copy_size > mp3fp->flen)
         {
             copy_size = mp3fp->flen - mp3fp->fpos;
         }
         fread (mp3fp->fbuf+unproc_data_size, 1, copy_size, mp3fp->fp);
         mp3fp->fbsize = unproc_data_size + copy_size;
         mp3fp->fpos += copy_size;
         /*Hand off the buffer to the mp3 input stream*/
         mad_stream_buffer(stream, mp3fp->fbuf, mp3fp->fbsize);
         ret_code = MAD_FLOW_CONTINUE;
     }
     else
     {
         ret_code = MAD_FLOW_STOP;
     }
     return  ret_code;
}
/*
* The following utility routine performs simple rounding, clipping, and
* scaling of MAD's high-resolution samples down to 16 bits. It does not
* perform any dithering or noise shaping, which would be recommended to
* obtain any exceptional audio quality. It is therefore not recommended to
* use this routine if high-quality output is desired.
*/
static  inline
signed  int  scale(mad_fixed_t sample)
{
     /* round */
     sample += (1L <= MAD_F_FRACBITS - 16);
     if (sample >= MAD_F_ONE)
         sample = MAD_F_ONE - 1;
     else  if (sample < -MAD_F_ONE)
         sample = -MAD_F_ONE;
     return  sample >> (MAD_F_FRACBITS + 1 - 16);
}
/*
* This is the output callback function. It is called after each frame of
* MPEG audio data has been completely decoded. The purpose of this callback
* is to output (or play) the decoded PCM audio.
*/
static
enum  mad_flow output( void  *data,
struct  mad_header  const  *header,
struct  mad_pcm *pcm)
{
     unsigned  int  nchannels, nsamples;
     unsigned  int  rate;
     mad_fixed_t  const  *left_ch, *right_ch;
     /* pcm->samplerate contains the sampling frequency */
     rate = pcm->samplerate;
     nchannels = pcm->channels;
     nsamples = pcm->length;
     left_ch = pcm->samples[0];
     right_ch = pcm->samples[1];
     /* update the sample rate of dsp*/
     if (rate != prerate)
     {
         ioctl(soundfd, SNDCTL_DSP_SPEED, &rate);
         prerate = rate;
     }
     while  (nsamples--)
     {
         signed  int  sample;
         /* output sample(s) in 16-bit signed little-endian PCM */
         sample = scale(*left_ch++);
         writedsp((sample >> 0) & 0xff);
         writedsp((sample >> 8) & 0xff);
         if  (nchannels == 2)
         {
             sample = scale(*right_ch++);
             writedsp((sample >> 0) & 0xff);
             writedsp((sample >> 8) & 0xff);
         }
     }
     return  MAD_FLOW_CONTINUE;
}
/*
* This is the error callback function. It is called whenever a decoding
* error occurs. The error is indicated by stream->error; the list of
* possible MAD_ERROR_* errors can be found in the mad.h (or stream.h)
* header file.
*/
static  enum  mad_flow error( void  *data,
struct  mad_stream *stream,
struct  mad_frame *frame)
{
     mp3_file *mp3fp = data;
     fprintf (stderr,  "decoding error 0x%04x (%s) at byte offset %u\n" ,
     stream->error, mad_stream_errorstr(stream),
     stream->this_frame - mp3fp->fbuf);
     /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */
     return  MAD_FLOW_CONTINUE;
}
/*
* This is the function called by main() above to perform all the decoding.
* It instantiates a decoder object and configures it with the input,
* output, and error callback functions above. A single call to
* mad_decoder_run() continues until a callback function returns
* MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and
* signal an error).
*/
static  int  decode(mp3_file *mp3fp)
{
     struct  mad_decoder decoder;
     int  result;
     /* configure input, output, and error functions */
     mad_decoder_init(&decoder, mp3fp,
     input, 0  /* header */ , 0  /* filter */ , output,
     error, 0  /* message */ );
     /* start decoding */
     result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
     /* release the decoder */
     mad_decoder_finish(&decoder);
     return  result;
}



   编译:gcc -o mp3player MP3player.c -lmad

   运行:./mp3player xxx.mp3

   至此,一个简易MP3播放器就写好了。


   程序已亲自验证,请放心阅览。如有错误,欢迎批评指正。


   享受阳光,享受生活。愿与大家共同进步。




本文转自 006玩命 51CTO博客,原文链接:http://blog.51cto.com/weiyuqingcheng/1362179,如需转载请自行联系原作者
相关文章
|
3月前
|
安全 Linux vr&ar
Linux的动态库和静态库
Linux的动态库和静态库
|
22天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
67 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
3月前
|
Linux API
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
|
3月前
|
安全 Linux 图形学
Linux平台Unity下RTMP|RTSP低延迟播放器技术实现
本文介绍了在国产操作系统及Linux平台上,利用Unity实现RTMP/RTSP直播播放的方法。通过设置原生播放模块的回调函数,可将解码后的YUV数据传递给Unity进行渲染,实现低延迟播放。此外,还提供了播放器启动、参数配置及停止的相关代码示例,并概述了如何在Unity中更新纹理以显示视频帧。随着国产操作系统的发展,此类跨平台直播解决方案的需求日益增长,为开发者提供了灵活高效的开发方式。
|
3月前
|
编解码 算法 Linux
Linux平台下RTSP|RTMP播放器如何跟python交互投递RGB数据供视觉算法分析
在对接Linux平台的RTSP播放模块时,需将播放数据同时提供给Python进行视觉算法分析。技术实现上,可在播放时通过回调函数获取视频帧数据,并以RGB32格式输出。利用`SetVideoFrameCallBackV2`接口设定缩放后的视频帧回调,以满足算法所需的分辨率。回调函数中,每收到一帧数据即保存为bitmap文件。Python端只需读取指定文件夹中的bitmap文件,即可进行视频数据的分析处理。此方案简单有效,但应注意控制输出的bitmap文件数量以避免内存占用过高。
|
3月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
105 3
|
4月前
|
Oracle 关系型数据库 Linux
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
通过这一连串的步骤,可以专业且有效地在Linux下为Qt编译Oracle驱动库 `libqsqloci.so`,使得Qt应用能够通过OCI与Oracle数据库进行交互。这些步骤适用于具备一定Linux和Qt经验的开发者,并且能够为需要使用Qt开发数据库应用的专业人士提供指导。
139 1
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
|
3月前
|
Linux 网络安全 API
【Azure 应用服务】App Service For Linux 环境中,如何从App Service中获取GitHub私有库(Private Repos)的Deploy Key(RSA key)呢?
【Azure 应用服务】App Service For Linux 环境中,如何从App Service中获取GitHub私有库(Private Repos)的Deploy Key(RSA key)呢?
|
3月前
|
小程序 Linux 开发者
Linux之缓冲区与C库IO函数简单模拟
通过上述编程实例,可以对Linux系统中缓冲区和C库IO函数如何提高文件读写效率有了一个基本的了解。开发者需要根据应用程序的具体需求来选择合适的IO策略。
30 0
|
5月前
|
存储 Linux C语言
Linux|如何安装和运行多个 glibc 库
Linux|如何安装和运行多个 glibc 库
976 5