VLC在0.8.6C版本时,还保持着大部分代码对MSVC编译环境的兼容,到了0.9版本以后,就基本放弃了对MSVC的兼容性了。不过,要在MSVC环境里编译VLC最新版本,也还是有方法可以做到。
VC6的编译环境,补丁版本Service Pack5, Processor Pack SP5。
下面仅以一个plugin的移植编译过程来说明。
1. 首先,将VLC-0.8.6C的msvc目录拷贝到vlc-0.9.9a目录下,这里面有多数plugin的VC6的.dsp工程文件。
2. 用VC6打开plugin_mp4.dsp,先尝试编译,错误如下:
--------------------Configuration: plugin_mp4 - Win32 Debug--------------------
Compiling...
mp4.c
d:\source\vlc-0.9.9a\include\vlc_common.h(52) : fatal error C1083: Cannot open include file: 'inttypes.h': No such file or directory
libmp4.c
d:\source\vlc-0.9.9a\include\vlc_common.h(52) : fatal error C1083: Cannot open include file: 'inttypes.h': No such file or directory
drms.c
d:\source\vlc-0.9.9a\modules\demux\mp4\drms.c(35) : fatal error C1083: Cannot open include file: 'drmsvl.h': No such file or directory
Error executing cl.exe.
libmp4_plugin.dll - 3 error(s), 0 warning(s)
3. inttypes.h这个头文件在MSVC的环境里是没有的,不过没关系,这个很容易处理。首先增加一个预处理定义_VLC_VC6,确保新的改动不要影响到原有的代码
Vlc_common.h中:
#ifndef _VLC_VC6
#include <inttypes.h>
#endif
4. 再次编译,错误信息如下:
--------------------Configuration: plugin_mp4 - Win32 Debug--------------------
Compiling...
mp4.c
d:\source\vlc-0.9.9a\include\vlc_common.h(58) : fatal error C1083: Cannot open include file: 'stdbool.h': No such file or directory
libmp4.c
d:\source\vlc-0.9.9a\include\vlc_common.h(58) : fatal error C1083: Cannot open include file: 'stdbool.h': No such file or directory
drms.c
d:\source\vlc-0.9.9a\modules\demux\mp4\drms.c(35) : fatal error C1083: Cannot open include file: 'drmsvl.h': No such file or directory
Error executing cl.exe.
libmp4_plugin.dll - 3 error(s), 0 warning(s)
5. stdbool.h也是一个MSVC环境中没有的头文件,依法炮制
vlc_common.h中:
#ifndef __cplusplus
#ifndef _VLC_VC6
# include <stdbool.h>
#else
typedef char bool;
#define true 1
#define false 0
#endif
6. msvc目录下有个config.h头文件,是用于MSVC环境适配的,增加预处理定义HAVE_CONFIG_H,把它加进来
7. 在vlc_config.h末尾增加如下类型定义,补充inttypes.h里的类型定义。
#ifdef _VLC_VC6
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#endif
8. 再次编译,出错信息如下:
--------------------Configuration: plugin_mp4 - Win32 Debug--------------------
Compiling...
mp4.c
d:\source\vlc-0.9.9a\include\vlc_threads.h(334) : warning C4013: 'SignalObjectAndWait' undefined; assuming extern returning int
d:\source\vlc-0.9.9a\include\vlc_threads.h(529) : warning C4013: 'InitializeCriticalSectionAndSpinCount' undefined; assuming extern returning int
d:\source\vlc-0.9.9a\include\vlc_arrays.h(458) : error C2143: syntax error : missing ';' before 'type'
d:\source\vlc-0.9.9a\include\vlc_arrays.h(459) : error C2143: syntax error : missing ';' before 'type'
d:\source\vlc-0.9.9a\include\vlc_arrays.h(461) : error C2065: 'p_entry' : undeclared identifier
d:\source\vlc-0.9.9a\include\vlc_arrays.h(466) : error C2223: left of '->psz_key' must point to struct/union
d:\source\vlc-0.9.9a\include\vlc_arrays.h(466) : error C2198: 'strcmp' : too few actual parameters
d:\source\vlc-0.9.9a\include\vlc_arrays.h(467) : error C2223: left of '->p_value' must point to struct/union
d:\source\vlc-0.9.9a\include\vlc_arrays.h(467) : warning C4033: 'vlc_dictionary_value_for_key' must return a value
d:\source\vlc-0.9.9a\include\vlc_arrays.h(468) : error C2223: left of '->p_next' must point to struct/union
省略。。。
9. vlc_arrays.h(458)的错误是由于VC6认为C文件的变量定义没有位于函数的开始位置,这类错误没有别的办法,手工修改一下:(类似的编译错误就不再重复说明)
int i_pos;
struct vlc_dictionary_entry_t * p_entry;
if( !p_dict->p_entries )
return kVLCDictionaryNotFound;
i_pos = DictHash( psz_key, p_dict->i_size );
p_entry = p_dict->p_entries[i_pos];
10. 如下编译错误
d:\source\vlc-0.9.9a\include\vlc_common.h(756) : error C2632: 'long' followed by 'long' is illegal
将long long替换为int64_t即可
11. 如下编译错误
d:\source\vlc-0.9.9a\include\vlc_messages.h(93) : error C2010: '.' : unexpected in macro formal parameter list
VC6不支持变参宏定义,因此把这段代码修改为:
#ifndef _VLC_VC6
#define msg_Info( p_this, ... ) \
__msg_Generic( VLC_OBJECT(p_this), VLC_MSG_INFO, \
MODULE_STRING, __VA_ARGS__ )
#define msg_Err( p_this, ... ) \
__msg_Generic( VLC_OBJECT(p_this), VLC_MSG_ERR, \
MODULE_STRING, __VA_ARGS__ )
#define msg_Warn( p_this, ... ) \
__msg_Generic( VLC_OBJECT(p_this), VLC_MSG_WARN, \
MODULE_STRING, __VA_ARGS__ )
#define msg_Dbg( p_this, ... ) \
__msg_Generic( VLC_OBJECT(p_this), VLC_MSG_DBG, \
MODULE_STRING, __VA_ARGS__ )
#else
#define MSG_QUEUE_NORMAL 0
#define MSG_QUEUE_HTTPD_ACCESS 1
inline void msg_Info( void *p_this, const char *psz_format, ... )
{
va_list ap;
va_start( ap, psz_format );
__msg_GenericVa( ( vlc_object_t *)p_this, VLC_MSG_INFO, MODULE_STRING,
psz_format, ap );
va_end(ap);
}
inline void msg_Err( void *p_this, const char *psz_format, ... )
{
va_list ap;
va_start( ap, psz_format );
__msg_GenericVa( ( vlc_object_t *)p_this,VLC_MSG_ERR, MODULE_STRING,
psz_format, ap );
va_end(ap);
}
inline void msg_Warn( void *p_this, const char *psz_format, ... )
{
va_list ap;
va_start( ap, psz_format );
__msg_GenericVa( ( vlc_object_t *)p_this, VLC_MSG_WARN, MODULE_STRING,
psz_format, ap );
va_end(ap);
}
inline void msg_Dbg( void *p_this, const char *psz_format, ... )
{
va_list ap;
va_start( ap, psz_format );
__msg_GenericVa( ( vlc_object_t *)p_this, VLC_MSG_DBG, MODULE_STRING,
psz_format, ap );
va_end(ap);
}
#endif
12. 如下编译错误:
d:\source\vlc-0.9.9a\include\vlc_messages.h(113) : error C2065: 'MODULE_STRING' : undeclared identifier
在config.h中增加如下定义
#define STRINGIFY( z ) UGLY_KLUDGE( z )
#define UGLY_KLUDGE( z ) #z
#define CONCATENATE( y, z ) CRUDE_HACK( y, z )
#define CRUDE_HACK( y, z ) y##__##z
# define _(String) (String)
# define N_(String) (String)
#define MODULE_STRING STRINGIFY( MODULE_NAME )
typedef int ssize_t;
typedef int mode_t;
typedef int vlc_bool_t;
typedef int socklen_t;
13. 如下编译错误:
d:\source\vlc-0.9.9a\include\vlc_charset.h(35) : fatal error C1083: Cannot open include file: 'dirent.h': No such file or directory
其实dirent.h在WINDOWS平台上并不需要,将vlc_charset.h对应代码修改为:
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
另外在vlc_common.h中增加:
# ifndef HAVE_DIRENT_H
typedef void DIR;
# ifndef FILENAME_MAX
# define FILENAME_MAX (260)
# endif
struct dirent
{
long d_ino; /* Always zero. */
unsigned short d_reclen; /* Always zero. */
unsigned short d_namlen; /* Length of name in d_name. */
char d_name[FILENAME_MAX]; /* File name. */
};
# define opendir vlc_opendir
# define readdir vlc_readdir
# define closedir vlc_closedir
# define rewinddir vlc_rewindir
void *vlc_opendir (const char *);
void *vlc_readdir (void *);
int vlc_closedir(void *);
void vlc_rewinddir(void *);
# endif
14. 如下编译错误:
D:\Source\vlc-0.9.9a\modules\demux\mp4\libmp4.c(227) : error C2146: syntax error : missing ')' before identifier 'PRId64'
在config.h后面增加如下宏定义:
#define INT64_C(val) val##i64
#define _64BITARG_ "I64"
#define PRId64 _64BITARG_"d"
#define PRIu64 _64BITARG_"u"
15. 如下编译错误:
d:\source\vlc-0.9.9a\modules\demux\mp4\mp4.c(1019) : error C2146: syntax error : missing ';' before identifier 'realloc'
修改vlc_arrays.h中TAB_APPEND的定义:
#ifndef _VLC_VC6
#define TAB_APPEND( count, tab, p ) \
TAB_APPEND_CAST( , count, tab, p )
#else
#define TAB_APPEND( count, tab, p ) \
do { \
if( (count) > 0 ) \
(tab) = realloc( tab, sizeof( void ** ) * ( (count) + 1 ) ); \
else \
(tab) = malloc( sizeof( void ** ) ); \
(tab)[count] = (p); \
(count)++; \
} while(0)
#endif
16. 如下编译错误:
d:\source\vlc-0.9.9a\modules\demux\mp4\drms.c(35) : fatal error C1083: Cannot open include file: 'drmsvl.h': No such file or directory
drmsvl.h也是不需要的,增加预处理编译选项__LIBVLC__即可。
17. 如下编译错误:
d:\source\vlc-0.9.9a\modules\demux\mp4\drms.c(818) : error C2057: expected constant expression
VC6不支持声明编译阶段长度不确定的数组,将其改为足够长的定长数据即可。
18. 编译错误:
D:\Source\vlc-0.9.9a\modules\demux\mp4\drms.c(1805) : error C2065: 'CSIDL_COMMON_APPDATA' : undeclared identifier
在config.h里定义:
#define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data
19. 至此,编译错误就都被消灭了,但还不能高兴太早,还有很多链接错误,大量的符号链接不上。
mp4.obj : error LNK2001: unresolved external symbol _vlc_config_set
mp4.obj : error LNK2001: unresolved external symbol _vlc_config_create
mp4.obj : error LNK2001: unresolved external symbol _vlc_module_set
mp4.obj : error LNK2001: unresolved external symbol ___vlc_object_release
mp4.obj : error LNK2001: unresolved external symbol ___vlc_gc_decref
mp4.obj : error LNK2001: unresolved external symbol _input_item_AddSubItem
mp4.obj : error LNK2001: unresolved external symbol _input_item_CopyOptions
mp4.obj : error LNK2001: unresolved external symbol ___input_item_NewExt
mp4.obj : error LNK2001: unresolved external symbol _asprintf
mp4.obj : error LNK2001: unresolved external symbol _input_GetItem
mp4.obj : error LNK2001: unresolved external symbol ___vlc_object_find
mp4.obj : error LNK2001: unresolved external symbol _stream_Control
libmp4.obj : error LNK2001: unresolved external symbol _stream_Control
mp4.obj : error LNK2001: unresolved external symbol _stream_Peek
libmp4.obj : error LNK2001: unresolved external symbol _stream_Peek
mp4.obj : error LNK2001: unresolved external symbol _stream_Block
mp4.obj : error LNK2001: unresolved external symbol _EnsureUTF8
mp4.obj : error LNK2001: unresolved external symbol ___msg_GenericVa
libmp4.obj : error LNK2001: unresolved external symbol ___msg_GenericVa
mp4.obj : error LNK2001: unresolved external symbol _strndup
mp4.obj : error LNK2001: unresolved external symbol _stream_Read
libmp4.obj : error LNK2001: unresolved external symbol _stream_Read
mp4.obj : error LNK2001: unresolved external symbol _es_format_Init
mp4.obj : error LNK2001: unresolved external symbol _es_format_Clean
libmp4.obj : error LNK2001: unresolved external symbol _strnlen
libmp4.obj : error LNK2001: unresolved external symbol _config_GetHomeDir
libmp4.obj : error LNK2001: unresolved external symbol _vasprintf
drms.obj : error LNK2001: unresolved external symbol _EndMD5
drms.obj : error LNK2001: unresolved external symbol _AddMD5
drms.obj : error LNK2001: unresolved external symbol _InitMD5
drms.obj : error LNK2001: unresolved external symbol _utf8_fopen
drms.obj : error LNK2001: unresolved external symbol _strtoll
plugins\libmp4_plugin.dll : fatal error LNK1120: 28 unresolved externals
这是因为0.8.6c版本中,MSVC环境中,plugin是通过一个全局函数表来调用libvlccore中的库函数,而到了0.9.9a版本,全局函数表消失了,因此所有对libvlccore库函数的调用都变成了链接不上的符号。
解决方案很简单,用dll2lib生成libvlccore.dll对应的libvlccore.lib文件,然后把libvlccore.lib链接进来。
现在,就只剩下如下几个链接错误了:
mp4.obj : error LNK2001: unresolved external symbol _asprintf
mp4.obj : error LNK2001: unresolved external symbol _strndup
libmp4.obj : error LNK2001: unresolved external symbol _strnlen
libmp4.obj : error LNK2001: unresolved external symbol _vasprintf
drms.obj : error LNK2001: unresolved external symbol _strtoll
这些都是MSVC环境中不存在的几个API,事实上,VLC源码包中也提供了MSVC环境下的实现,在vlc_fixups.h中。但是vlc_fixups.h中又有很多不相关的其他东西,为了简单起见,可以新添加一个misc.c文件到项目中,并把vlc_fixups.h中的这几个文件的实现拷贝过来。
再次重新编译,编译成功!