Borland Builder C++ 6 中的 CoreAudio API

Posted

技术标签:

【中文标题】Borland Builder C++ 6 中的 CoreAudio API【英文标题】:CoreAudio API in Borland Builder C++ 6 【发布时间】:2015-01-08 12:01:59 【问题描述】:

我需要使用 CoreAudio API 来控制 Windows 7 和 borland builder c++ 中的音量,这似乎是不可能的。 由于版本问题等原因,我似乎无法将这些 Windows SDK 头文件用于 builder c++。

【问题讨论】:

抱歉,您到底为什么要使用 C++ Builder 6? Visual Studio 2012 的社区版是免费的,而 C++B6 是一个非常古老的 IDE,带有非常古老的编译器。 在这种情况下,除非您能从 2002 年左右获得可以使用的 Windows SDK 版本,否则我认为这是徒劳的。 由于旧版本的 Windows SDK 不支持 CoreAudio API,您认为它会如何工作? 这听起来不太可能,旧的 SDK 没有您需要的 API,并且您不能将新的 SDK 与旧的编译器一起使用。你需要和你的经理谈谈他对这个项目的期望和你的限制。 一种解决方案是生成一个简单的 win32 dll,使用此 API 在最新的 Visual Studio 中导出必要的功能,并在我的项目中加载和使用该 dll。其他人可以从新 SDK 获取此 API 的头文件,并在旧 SDK 中使用它们以及它们的 dll。标头将带来所有依赖项以及删除额外的 deftypes 和依赖项。类似的东西。不过必须讨论。 【参考方案1】:

__RPC__in 定义在 rpcsal.h 中,它不包含在 C++Builder 6 中(它是在 C++Builder 2007 中添加的)。您可以根据需要在代码中手动定义__RPC__in(和其他相关定义),然后再包括mmdeviceapi.h,例如:

#ifndef __RPCSAL_H_VERSION__
#define __RPC_in
// other related defines, such as __RPC__out...
#endif

#include <mmdeviceapi.h>

__RPC__in 和其他相关符号只是帮助代码自我记录的预处理器宏,它们实际上对 C++ 编译器没有任何作用(但对 Microsoft 的 PreFAST 分析工具有用)。

这里是rpcsal.h的内容(去掉了PREFAST定义,否则内容太大,***无法接受):

#pragma option push -b -a8 -pc -A- /*P_O_Push*/
/****************************************************************\
*                                                                *
* rpcsal.h - markers for documenting the semantics of RPC APIs   *
*                                                                *
* Version 1.0                                                    *
*                                                                *
* Copyright (c) 2004 Microsoft Corporation. All rights reserved. *
*                                                                *
\****************************************************************/

// -------------------------------------------------------------------------------
// Introduction
//
// rpcsal.h provides a set of annotations to describe how RPC functions use their
// parameters - the assumptions it makes about them, adn the guarantees it makes 
// upon finishing.  These annotations are similar to those found in specstrings.h,
// but are designed to be used by the MIDL compiler when it generates annotations
// enabled header files.
//
// IDL authors do not need to annotate their functions declarations.  The MIDL compiler
// will interpret the IDL directives and use one of the annotations contained 
// in this header.  This documentation is intended to help those trying to  understand 
// the MIDL-generated header files or those who maintain their own copies of these files.
//
// -------------------------------------------------------------------------------
// Differences between rpcsal.h and specstrings.h
// 
// There are a few important differences between the annotations found in rpcsal.h and
// those in specstrings.h:
// 
// 1. [in] parameters are not marked as read-only.  They may be used for scratch space 
// at the server and changes will not affect the client.
// 2. String versions of each macro alleviates the need for a special type definition
//
// -------------------------------------------------------------------------------
// Interpreting RPC Annotations
//
// These annotations are interpreted precisely in the same way as those in specstrings.h.  
// Please refer to that header for information related to general usage in annotations. 
//
// To construct an RPC annotation, concatenate the appropriate value from each category
// along with a leading __RPC_.  A typical annotation looks like "__RPC__in_string".
//
// |----------------------------------------------------------------------------------|
// | RPC Annotations                                                                  |
// |------------|------------|---------|--------|----------|----------|---------------|
// |   Level    |   Usage    |  Size   | Output | Optional |  String  |  Parameters   |
// |------------|------------|---------|--------|----------|----------|---------------|
// | <>         | <>         | <>      | <>     | <>       | <>       | <>            |
// | _deref     | _in        | _ecount | _full  | _opt     | _string  | (size)        |
// | _deref_opt | _out       | _bcount | _part  |          |          | (size,length) |
// |            | _inout     |         |        |          |          |               |
// |            |            |         |        |          |          |               |
// |------------|------------|---------|--------|----------|----------|---------------|
//
// Level: Describes the buffer pointer's level of indirection from the parameter or
//          return value 'p'.
//
// <>         : p is the buffer pointer.
// _deref     : *p is the buffer pointer. p must not be NULL.
// _deref_opt : *p may be the buffer pointer. p may be NULL, in which case the rest of
//                the annotation is ignored.
//
// Usage: Describes how the function uses the buffer.
//
// <>     : The buffer is not accessed. If used on the return value or with _deref, the
//            function will provide the buffer, and it will be uninitialized at exit.
//            Otherwise, the caller must provide the buffer. This should only be used
//            for alloc and free functions.
// _in    : The function will only read from the buffer. The caller must provide the
//            buffer and initialize it. Cannot be used with _deref.
// _out   : The function will only write to the buffer. If used on the return value or
//            with _deref, the function will provide the buffer and initialize it.
//            Otherwise, the caller must provide the buffer, and the function will
//            initialize it.
// _inout : The function may freely read from and write to the buffer. The caller must
//            provide the buffer and initialize it. If used with _deref, the buffer may
//            be reallocated by the function.
//
// Size: Describes the total size of the buffer. This may be less than the space actually
//         allocated for the buffer, in which case it describes the accessible amount.
//
// <>      : No buffer size is given. If the type specifies the buffer size (such as
//             with LPSTR and LPWSTR), that amount is used. Otherwise, the buffer is one
//             element long. Must be used with _in, _out, or _inout.
// _ecount : The buffer size is an explicit element count.
// _bcount : The buffer size is an explicit byte count.
//
// Output: Describes how much of the buffer will be initialized by the function. For
//           _inout buffers, this also describes how much is initialized at entry. Omit this
//           category for _in buffers; they must be fully initialized by the caller.
//
// <>    : The type specifies how much is initialized. For instance, a function initializing
//           an LPWSTR must NULL-terminate the string.
// _full : The function initializes the entire buffer.
// _part : The function initializes part of the buffer, and explicitly indicates how much.
//
// Optional: Describes if the buffer itself is optional.
//
// <>   : The pointer to the buffer must not be NULL.
// _opt : The pointer to the buffer might be NULL. It will be checked before being dereferenced.
//
// String: Describes if the buffer is NULL terminated
//
// <>      : The buffer is not assumed to be NULL terminated
// _string : The buffer is assumed to be NULL terminated once it has been initialized
//
// Parameters: Gives explicit counts for the size and length of the buffer.
//
// <>            : There is no explicit count. Use when neither _ecount nor _bcount is used.
// (size)        : Only the buffer's total size is given. Use with _ecount or _bcount but not _part.
// (size,length) : The buffer's total size and initialized length are given. Use with _ecount_part
//                   and _bcount_part.
//
// Notes:
//
// 1. Specifying two buffer annotations on a single parameter results in unspecified behavior
//    (e.g. __RPC__in_bcount(5) __RPC__out_bcount(6)
// 
// 2. The size of the buffer and the amount that has been initialized are separate concepts.  
//    Specify the size using _ecount or _bcount.  Specify the amount that is initialized using 
//    _full, _part, or _string.  As a special case, a single element buffer does not need 
//    _ecount, _bcount, _full, or _part
// 
// 3. The count may be less than the total size of the buffer in which case it describes the 
//    accessible portion. 
// 
// 4. "__RPC__opt" and "__RPC_deref" are not valid annotations.
// 
// 5. The placement of _opt when using _deref is important:
//      __RPC__deref_opt_...      : Input may be NULL
//      __RPC__deref_..._opt      : Output may be NULL
//      __RPC__deref_opt_..._opt  : Both input and output may be NULL
//

#pragma once

#include <specstrings.h>

#ifndef __RPCSAL_H_VERSION__
#define __RPCSAL_H_VERSION__        ( 100 )
#endif // __RPCSAL_H_VERSION__

#ifdef __REQUIRED_RPCSAL_H_VERSION__
    #if ( __RPCSAL_H_VERSION__ < __REQUIRED_RPCSAL_H_VERSION__ )
        #error incorrect <rpcsal.h> version. Use the header that matches with the MIDL compiler.
    #endif
#endif


#ifdef  __cplusplus
extern "C" 
#endif  // #ifdef __cplusplus

#if (_MSC_VER >= 1000) && !defined(__midl) && defined(_PREFAST_)

// PREFAST defines removed for brevity...

#else   // not prefast

#define __RPC__range(min,max)
#define __RPC__in_range(min,max)

#define __RPC__in           
#define __RPC__in_string
#define __RPC__in_opt_string
#define __RPC__in_ecount(size) 
#define __RPC__in_ecount_full(size)
#define __RPC__in_ecount_full_string(size)
#define __RPC__in_ecount_part(size, length)
#define __RPC__in_ecount_full_opt(size)
#define __RPC__in_ecount_full_opt_string(size)
#define __RPC__inout_ecount_full_opt_string(size)
#define __RPC__in_ecount_part_opt(size, length)
#define __RPC__in_xcount(size) 
#define __RPC__in_xcount_full(size)
#define __RPC__in_xcount_full_string(size)
#define __RPC__in_xcount_part(size, length)
#define __RPC__in_xcount_full_opt(size)
#define __RPC__in_xcount_full_opt_string(size)
#define __RPC__inout_xcount_full_opt_string(size)
#define __RPC__in_xcount_part_opt(size, length)

#define __RPC__deref_in 
#define __RPC__deref_in_string
#define __RPC__deref_in_opt
#define __RPC__deref_in_opt_string
#define __RPC__deref_opt_in
#define __RPC__deref_opt_in_string
#define __RPC__deref_opt_in_opt
#define __RPC__deref_opt_in_opt_string
#define __RPC__deref_in_ecount(size) 
#define __RPC__deref_in_ecount_part(size, length) 
#define __RPC__deref_in_ecount_full(size) 
#define __RPC__deref_in_ecount_full_opt(size)
#define __RPC__deref_in_ecount_full_string(size)
#define __RPC__deref_in_ecount_full_opt_string(size)
#define __RPC__deref_in_ecount_opt(size) 
#define __RPC__deref_in_ecount_opt_string(size)
#define __RPC__deref_in_ecount_part_opt(size, length) 
#define __RPC__deref_in_xcount(size) 
#define __RPC__deref_in_xcount_part(size, length) 
#define __RPC__deref_in_xcount_full(size) 
#define __RPC__deref_in_xcount_full_opt(size)
#define __RPC__deref_in_xcount_full_string(size)
#define __RPC__deref_in_xcount_full_opt_string(size)
#define __RPC__deref_in_xcount_opt(size) 
#define __RPC__deref_in_xcount_opt_string(size)
#define __RPC__deref_in_xcount_part_opt(size, length) 

// [out]
#define __RPC__out     
#define __RPC__out_ecount(size) 
#define __RPC__out_ecount_part(size, length) 
#define __RPC__out_ecount_full(size)
#define __RPC__out_ecount_full_string(size)
#define __RPC__out_xcount(size) 
#define __RPC__out_xcount_part(size, length) 
#define __RPC__out_xcount_full(size)
#define __RPC__out_xcount_full_string(size)

// [in,out] 
#define __RPC__inout                                   
#define __RPC__inout_string
#define __RPC__opt_inout
#define __RPC__inout_ecount(size)                     
#define __RPC__inout_ecount_part(size, length)    
#define __RPC__inout_ecount_full(size)          
#define __RPC__inout_ecount_full_string(size)          
#define __RPC__inout_xcount(size)                     
#define __RPC__inout_xcount_part(size, length)    
#define __RPC__inout_xcount_full(size)          
#define __RPC__inout_xcount_full_string(size)          

// [in,unique] 
#define __RPC__in_opt       
#define __RPC__in_ecount_opt(size)   
#define __RPC__in_xcount_opt(size)   


// [in,out,unique] 
#define __RPC__inout_opt    
#define __RPC__inout_opt_string    
#define __RPC__inout_ecount_opt(size)  
#define __RPC__inout_ecount_part_opt(size, length) 
#define __RPC__inout_ecount_full_opt(size)     
#define __RPC__inout_ecount_full_string(size)
#define __RPC__inout_xcount_opt(size)  
#define __RPC__inout_xcount_part_opt(size, length) 
#define __RPC__inout_xcount_full_opt(size)     
#define __RPC__inout_xcount_full_string(size)

// [out] **
#define __RPC__deref_out   
#define __RPC__deref_out_string
#define __RPC__deref_out_opt 
#define __RPC__deref_out_opt_string
#define __RPC__deref_out_ecount(size) 
#define __RPC__deref_out_ecount_part(size, length) 
#define __RPC__deref_out_ecount_full(size)  
#define __RPC__deref_out_ecount_full_string(size)
#define __RPC__deref_out_xcount(size) 
#define __RPC__deref_out_xcount_part(size, length) 
#define __RPC__deref_out_xcount_full(size)  
#define __RPC__deref_out_xcount_full_string(size)


// [in,out] **, second pointer decoration. 
#define __RPC__deref_inout    
#define __RPC__deref_inout_string
#define __RPC__deref_inout_opt 
#define __RPC__deref_inout_opt_string
#define __RPC__deref_inout_ecount_full(size)
#define __RPC__deref_inout_ecount_full_string(size)
#define __RPC__deref_inout_ecount_opt(size) 
#define __RPC__deref_inout_ecount_part_opt(size, length) 
#define __RPC__deref_inout_ecount_full_opt(size) 
#define __RPC__deref_inout_ecount_full_opt_string(size) 
#define __RPC__deref_inout_xcount_full(size)
#define __RPC__deref_inout_xcount_full_string(size)
#define __RPC__deref_inout_xcount_opt(size) 
#define __RPC__deref_inout_xcount_part_opt(size, length) 
#define __RPC__deref_inout_xcount_full_opt(size) 
#define __RPC__deref_inout_xcount_full_opt_string(size) 

// #define __RPC_out_opt    out_opt is not allowed in rpc

// [in,out,unique] 
#define __RPC__deref_opt_inout  
#define __RPC__deref_opt_inout_string
#define __RPC__deref_opt_inout_ecount(size)     
#define __RPC__deref_opt_inout_ecount_part(size, length) 
#define __RPC__deref_opt_inout_ecount_full(size) 
#define __RPC__deref_opt_inout_ecount_full_string(size)
#define __RPC__deref_opt_inout_xcount(size)     
#define __RPC__deref_opt_inout_xcount_part(size, length) 
#define __RPC__deref_opt_inout_xcount_full(size) 
#define __RPC__deref_opt_inout_xcount_full_string(size)

#define __RPC__deref_out_ecount_opt(size) 
#define __RPC__deref_out_ecount_part_opt(size, length) 
#define __RPC__deref_out_ecount_full_opt(size) 
#define __RPC__deref_out_ecount_full_opt_string(size)
#define __RPC__deref_out_xcount_opt(size) 
#define __RPC__deref_out_xcount_part_opt(size, length) 
#define __RPC__deref_out_xcount_full_opt(size) 
#define __RPC__deref_out_xcount_full_opt_string(size)

#define __RPC__deref_opt_inout_opt      
#define __RPC__deref_opt_inout_opt_string
#define __RPC__deref_opt_inout_ecount_opt(size)   
#define __RPC__deref_opt_inout_ecount_part_opt(size, length) 
#define __RPC__deref_opt_inout_ecount_full_opt(size) 
#define __RPC__deref_opt_inout_ecount_full_opt_string(size) 
#define __RPC__deref_opt_inout_xcount_opt(size)   
#define __RPC__deref_opt_inout_xcount_part_opt(size, length) 
#define __RPC__deref_opt_inout_xcount_full_opt(size) 
#define __RPC__deref_opt_inout_xcount_full_opt_string(size) 

#define __RPC_full_pointer  
#define __RPC_unique_pointer
#define __RPC_ref_pointer
#define __RPC_string                               


#endif

#ifdef  __cplusplus

#endif


#pragma option pop /*P_O_Pop*/

那么你可以这样做:

#include "rpcsal.h"
#include <mmdeviceapi.h>

【讨论】:

嗨,谢谢你的回答,虽然我们想出了一个解决方案,为 borland 的 mmdeviceapi.idl 生成代码以键入 lib,然后使用实用程序 tlibimp.exe然后只保留我们需要的功能。稍后我们还必须获取 IAudioEndpointVolume 接口的代码和更多的代码来准备一个紧凑的头文件。为了使用这些类和接口,我们编写了一个小的包装类。现在一切正常:)

以上是关于Borland Builder C++ 6 中的 CoreAudio API的主要内容,如果未能解决你的问题,请参考以下文章

Borland C++ Builder 6 上的奇怪链接器错误

虚拟内存地址空间不足(Borland C++ Builder 6 程序)

Borland C++ Builder 中的 Windows 子类化

Borland C++ Builder 6.0的详细说明

添加了库; Borland C++ Builder 无故暂停

在 Borland C++ 6 中从 Windows 获取程序文件目录