我在下面的类中声明了一个友元函数。
班级模型
func createP12(secCertificate: SecCertificate, secPrivateKey: SecKey) {
// Read certificate
// Convert sec certificate to DER certificate
let derCertificate = SecCertificateCopyData(secCertificate)
// Create strange pointer to read DER certificate with OpenSSL
// data must be a two-dimensional array containing the pointer to the DER certificate as single element at position [0][0]
let certificatePointer = CFDataGetBytePtr(derCertificate)
let certificateLength = CFDataGetLength(derCertificate)
let certificateData = UnsafeMutablePointer<UnsafePointer<UInt8>?>.allocate(capacity: 1)
certificateData.pointee = certificatePointer
// Read DER certificate
let certificate = d2i_X509(nil, certificateData, certificateLength)
// Print certificate
X509_print_fp(stdout, certificate)
// Read private key
// Convert sec key to PEM key
let tempTag = "bundle.temp"
let tempAttributes = [
kSecClass: kSecClassKey,
kSecAttrApplicationTag: tempTag,
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecValueRef: secPrivateKey,
kSecReturnData: kCFBooleanTrue
] as NSDictionary
var privateKeyRef: AnyObject?
// Store private key in keychain
SecItemDelete(tempAttributes)
guard SecItemAdd(tempAttributes, &privateKeyRef) == noErr else {
NSLog("Cannot store private key")
return
}
// Get private key data
guard let privateKeyData = privateKeyRef as? Data else {
NSLog("Cannot get private key data")
return
}
let pemPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\n\(privateKeyData.base64EncodedString())\n-----END RSA PRIVATE KEY-----\n"
// Delete private key in keychain
SecItemDelete(tempAttributes)
let privateKeyBuffer = BIO_new(BIO_s_mem())
pemPrivateKey.data(using: .utf8)!.withUnsafeBytes({ (bytes: UnsafePointer<Int8>) -> Void in
BIO_puts(privateKeyBuffer, bytes)
})
let privateKey = PEM_read_bio_PrivateKey(privateKeyBuffer, nil, nil, nil)
// !!! Remove in production: Print private key
PEM_write_PrivateKey(stdout, privateKey, nil, nil, 0, nil, nil)
// Check if private key matches certificate
guard X509_check_private_key(certificate, privateKey) == 1 else {
NSLog("Private key does not match certificate")
return
}
// Set OpenSSL parameters
OPENSSL_add_all_algorithms_noconf()
ERR_load_crypto_strings()
// Create P12 keystore
let passPhrase = UnsafeMutablePointer(mutating: ("" as NSString).utf8String)
let name = UnsafeMutablePointer(mutating: ("SSL Certificate" as NSString).utf8String)
guard let p12 = PKCS12_create(passPhrase, name, privateKey, certificate, nil, 0, 0, 0, 0, 0) else {
NSLog("Cannot create P12 keystore:")
ERR_print_errors_fp(stderr)
return
}
// Save P12 keystore
let fileManager = FileManager.default
let tempDirectory = NSTemporaryDirectory() as NSString
let path = tempDirectory.appendingPathComponent("ssl.p12")
fileManager.createFile(atPath: path, contents: nil, attributes: nil)
guard let fileHandle = FileHandle(forWritingAtPath: path) else {
NSLog("Cannot open file handle: \(path)")
return
}
let p12File = fdopen(fileHandle.fileDescriptor, "w")
i2d_PKCS12_fp(p12File, p12)
fclose(p12File)
fileHandle.closeFile()
}
#include "fileio.h"
class fileio;
class model
{
std::vector<element>m_elements;
public:
friend void fileio::element_iterator();
}
是element_iterator()
的公共函数。
班级档案
class fileio
#include "model.h"
class model;
class fileio
{
model* m_model;
public:
fileio(model*);
void element_iterator();
}
函数定义如下。
element_iterator()
我想使用friend函数从另一个类迭代void fileio::element_iterator()
{
for(auto &iter : m_model->m_elements)
{
//some functions
}
}
。但是我收到的错误如下:
错误:
m_elements
修改:
如果没有fileio.h中 model.h : error: invalid use of incomplete type 'class fileio'
friend void fileio::read_boundary();
model.h : error: forward declaration of 'class fileio'
class fileio;
modell.h : In member function 'void fileio::read_boundary()':
cmodel.h : error: 'std::vector<element> model::m_elements' is private
std::vector<element>m_elements;
fileio.cpp: error: within this context
for(auto iter:m_model->m_elements)
的前向声明,则会产生另一组错误,如下所示:
class model
如果我注释掉友元函数声明及其定义,那么程序将运行没有错误。 我该如何解决?
答案 0 :(得分:2)
而不是fileio
中的前向声明 model.h
,请包含其完整定义。
// fileio.h
class model;
class fileio
{
model* m_model;
public:
void element_iterator();
};
// model.h
#include "fileio.h"
class model
{
std::vector<int >m_elements;
public:
friend void fileio::element_iterator();
};
或者,您可以将整个fileio
课程设为friend
- 这样您就可以使用其转发声明,这可能是您想要的,具体取决于您的真实的情况。
// model.h
class fileio;
class model
{
std::vector<int >m_elements;
public:
friend class fileio;
};
// fileio.h
class model;
class fileio
{
model* m_model;
public:
void element_iterator();
};