我有许多不同格式的.h
文件。它们包括函数定义、变量定义等等。我的目标是提取所有函数名和它们各自的注解并Map它们。**我正在寻找一种使用Python实现这一目标的可行方法。**我尝试了以下方法:
pyc解析器
https://github.com/eliben/pycparser
我读了下面的博客文章关于我的问题,但我不能设法让它工作:https://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers
使用下面的代码,我得到了以下错误:pycparser.plyparser.ParseError: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_types.h:100:27: before: __darwin_va_list
import sys
from pycparser import parse_file
sys.path.extend(['.', '..'])
if __name__ == "__main__":
filename = "<pathToHeader>/file.h"
ast = parse_file(filename, use_cpp=True,
cpp_path='gcc',
cpp_args=['-E', r'<pathToPycparser>/utils/fake_libc_include'])
ast.show()
自行车库
https://pyclibrary.readthedocs.io/en/latest/
这实际上运行时没有出现错误,但在示例文件中找不到任何函数。
from pyclibrary import CParser
parser = CParser(["<pathToHeader>/file.h")])
print(parser)
pygccxml
https://pygccxml.readthedocs.io/en/master/index.html
运行下面的代码,我得到了许多错误,例如unknown type name 'NSString
,脚本在20个错误后停止,因为发出了太多的错误。
from pygccxml import utils
from pygccxml import declarations
from pygccxml import parser
generator_path, generator_name = utils.find_xml_generator()
xml_generator_config = parser.xml_generator_configuration_t(
xml_generator_path=generator_path,
xml_generator=generator_name)
filename = "<pathToHeader>/file.h"
decls = parser.parse([filename], xml_generator_config)
global_namespace = declarations.get_global_namespace(decls)
ns = global_namespace.namespace("ns")
脱氧
https://www.doxygen.nl/index.html
尽管Doxygen本身不是一个解析器,而更像是一个代码文档工具,但我用它得到了最好的结果。它创建了一个包含所有函数名(即使是正确解析的)和注解的xml输出。注解被标记为注解,甚至用它们的行号标注。然而,函数没有用行号标注,所以基本上不可能将正确的注解匹配到正确的函数。
自定义解析器
我自己创建了一个简单的解析器,它正在以某种方式工作,但我不能确定我涵盖了这些文件中使用的所有可能的C-语法,因为在这些文件中使用了不同的语法,而且我不能手动检查所有文件的语法,因为它们太多了。
functionComments = {}
inComment = False
comment = []
function = None
for i in range(0, len(lines)):
line = lines[i].strip()
if line.startswith("/*"):
inComment = True
elif line.endswith("*/"):
inComment = False
comment.append(line[:-2].strip())
if len(lines) > i+1 and lines[i+1].startswith("- ("):
functionName = lines[i+1]
counter = 2
while len(lines) > i+counter and lines[i+counter] != "\n":
functionName += " " + lines[i+counter].lstrip().split(" API_")[0]
counter += 1
if ":" in functionName:
functionNameParts = functionName.split(":")
functionNamePartsSplitBySpace = []
function = ""
for j in range(0, len(functionNameParts)-1):
functionNamePartsSplitBySpace.append(functionNameParts[j].split(" "))
for k in range(0, len(functionNamePartsSplitBySpace)):
function += functionNamePartsSplitBySpace[k][-1].split(")")[-1] + ":"
else:
function = lines[i+1].split(" NS_AVAILABLE")[0].split(")")[-1]
functionComments[function] = "\n".join(comment)
comment = []
function = None
else:
function = None
comment = []
elif inComment:
if line.startswith("* "):
comment.append(line[2:].strip())
else:
comment.append(line)
头文件示例
/*
* CLLocationManagerDelegate.h
* CoreLocation
*
* Copyright (c) 2008-2010 Apple Inc. All rights reserved.
*
*/
#import <Availability.h>
#import <Foundation/Foundation.h>
#import <CoreLocation/CLLocationManager.h>
#import <CoreLocation/CLRegion.h>
#import <CoreLocation/CLVisit.h>
NS_ASSUME_NONNULL_BEGIN
@class CLLocation;
@class CLHeading;
@class CLBeacon;
@class CLVisit;
/*
* CLLocationManagerDelegate
*
* Discussion:
* Delegate for CLLocationManager.
*/
@protocol CLLocationManagerDelegate<NSObject>
@optional
/*
* locationManager:didUpdateToLocation:fromLocation:
*
* Discussion:
* Invoked when a new location is available. oldLocation may be nil if there is no previous location
* available.
*
* This method is deprecated. If locationManager:didUpdateLocations: is
* implemented, this method will not be called.
*/
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation API_AVAILABLE(macos(10.6)) API_DEPRECATED("Implement -locationManager:didUpdateLocations: instead", ios(2.0, 6.0)) API_UNAVAILABLE(watchos, tvos);
/*
* locationManager:didUpdateLocations:
*
* Discussion:
* Invoked when new locations are available. Required for delivery of
* deferred locations. If implemented, updates will
* not be delivered to locationManager:didUpdateToLocation:fromLocation:
*
* locations is an array of CLLocation objects in chronological order.
*/
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations API_AVAILABLE(ios(6.0), macos(10.9));
/*
* locationManager:didUpdateHeading:
*
* Discussion:
* Invoked when a new heading is available.
*/
- (void)locationManager:(CLLocationManager *)manager
didUpdateHeading:(CLHeading *)newHeading API_AVAILABLE(ios(3.0), watchos(2.0)) API_UNAVAILABLE(tvos, macos);
/*
* locationManagerShouldDisplayHeadingCalibration:
*
* Discussion:
* Invoked when a new heading is available. Return YES to display heading calibration info. The display
* will remain until heading is calibrated, unless dismissed early via dismissHeadingCalibrationDisplay.
*/
- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager API_AVAILABLE(ios(3.0), watchos(2.0)) API_UNAVAILABLE(tvos, macos);
/*
* locationManager:didDetermineState:forRegion:
*
* Discussion:
* Invoked when there's a state transition for a monitored region or in response to a request for state via a
* a call to requestStateForRegion:.
*/
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region API_AVAILABLE(ios(7.0), macos(10.10)) API_UNAVAILABLE(watchos, tvos);
/*
* locationManager:didRangeBeacons:inRegion:
*
* Discussion:
* Invoked when a new set of beacons are available in the specified region.
* beacons is an array of CLBeacon objects.
* If beacons is empty, it may be assumed no beacons that match the specified region are nearby.
* Similarly if a specific beacon no longer appears in beacons, it may be assumed the beacon is no longer received
* by the device.
*/
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray<CLBeacon *> *)beacons
inRegion:(CLBeaconRegion *)region API_DEPRECATED_WITH_REPLACEMENT("Use locationManager:didRangeBeacons:satisfyingConstraint:", ios(7.0, 13.0)) API_UNAVAILABLE(macos, macCatalyst) API_UNAVAILABLE(watchos, tvos);
/*
* locationManager:rangingBeaconsDidFailForRegion:withError:
*
* Discussion:
* Invoked when an error has occurred ranging beacons in a region. Error types are defined in "CLError.h".
*/
- (void)locationManager:(CLLocationManager *)manager
rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region
withError:(NSError *)error API_DEPRECATED_WITH_REPLACEMENT("Use locationManager:didFailRangingBeaconsForConstraint:error:", ios(7.0, 13.0)) API_UNAVAILABLE(macos, macCatalyst) API_UNAVAILABLE(watchos, tvos);
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray<CLBeacon *> *)beacons
satisfyingConstraint:(CLBeaconIdentityConstraint *)beaconConstraint API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, tvos, macos);
- (void)locationManager:(CLLocationManager *)manager
didFailRangingBeaconsForConstraint:(CLBeaconIdentityConstraint *)beaconConstraint
error:(NSError *)error API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(watchos, tvos, macos);
/*
* locationManager:didEnterRegion:
*
* Discussion:
* Invoked when the user enters a monitored region. This callback will be invoked for every allocated
* CLLocationManager instance with a non-nil delegate that implements this method.
*/
- (void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region API_AVAILABLE(ios(4.0), macos(10.8)) API_UNAVAILABLE(watchos, tvos);
/*
* locationManager:didExitRegion:
*
* Discussion:
* Invoked when the user exits a monitored region. This callback will be invoked for every allocated
* CLLocationManager instance with a non-nil delegate that implements this method.
*/
- (void)locationManager:(CLLocationManager *)manager
didExitRegion:(CLRegion *)region API_AVAILABLE(ios(4.0), macos(10.8)) API_UNAVAILABLE(watchos, tvos);
/*
* locationManager:didFailWithError:
*
* Discussion:
* Invoked when an error has occurred. Error types are defined in "CLError.h".
*/
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error;
/*
* locationManager:monitoringDidFailForRegion:withError:
*
* Discussion:
* Invoked when a region monitoring error has occurred. Error types are defined in "CLError.h".
*/
- (void)locationManager:(CLLocationManager *)manager
monitoringDidFailForRegion:(nullable CLRegion *)region
withError:(NSError *)error API_AVAILABLE(ios(4.0), macos(10.8)) API_UNAVAILABLE(watchos, tvos);
/*
* locationManager:didChangeAuthorizationStatus:
*
* Discussion:
* Invoked when the authorization status changes for this application.
*/
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status API_AVAILABLE(ios(4.2), macos(10.7));
/*
* locationManager:didStartMonitoringForRegion:
*
* Discussion:
* Invoked when a monitoring for a region started successfully.
*/
- (void)locationManager:(CLLocationManager *)manager
didStartMonitoringForRegion:(CLRegion *)region API_AVAILABLE(ios(5.0), macos(10.8)) API_UNAVAILABLE(watchos, tvos);
/*
* Discussion:
* Invoked when location updates are automatically paused.
*/
- (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(watchos, tvos, macos);
/*
* Discussion:
* Invoked when location updates are automatically resumed.
*
* In the event that your application is terminated while suspended, you will
* not receive this notification.
*/
- (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(watchos, tvos, macos);
/*
* locationManager:didFinishDeferredUpdatesWithError:
*
* Discussion:
* Invoked when deferred updates will no longer be delivered. Stopping
* location, disallowing deferred updates, and meeting a specified criterion
* are all possible reasons for finishing deferred updates.
*
* An error will be returned if deferred updates end before the specified
* criteria are met (see CLError), otherwise error will be nil.
*/
- (void)locationManager:(CLLocationManager *)manager
didFinishDeferredUpdatesWithError:(nullable NSError *)error API_AVAILABLE(ios(6.0), macos(10.9)) API_UNAVAILABLE(watchos, tvos);
/*
* locationManager:didVisit:
*
* Discussion:
* Invoked when the CLLocationManager determines that the device has visited
* a location, if visit monitoring is currently started (possibly from a
* prior launch).
*/
- (void)locationManager:(CLLocationManager *)manager didVisit:(CLVisit *)visit API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(watchos, tvos, macos);
@end
NS_ASSUME_NONNULL_END
1条答案
按热度按时间jm81lzqq1#
按照克雷格Estey的建议,使用
castxml
(它使用clang
库),我能够通过使用以下命令(此处建议)提取函数名及其行号。命令行
将此命令应用于示例头文件会抛出错误
fatal error: 'Availability.h' file not found
,但AST创建成功(据我所知)。巨蟒
findComment()
是一个自定义方法,用于解析Doxygen.xml并提取注解。