从C ++在Mac OSX上启动一个打开的对话框

时间:2014-02-27 12:11:15

标签: c++ objective-c macos objective-c++

我有一个包含代码的头文件

#ifndef PLATFORM_DEPENDENCE
#define PLATFORM_DEPENDENCE

#define USE_MAC
#include "WindowsFunctions.h"
#include "MacFunctions.h

#endif

WindowsFunctions.h:

#ifndef WINTRANSFERINCLUDE
#define WINTRANSFERINCLUDE
#ifdef USE_WINDOWS

#include <string>
#include <boost/shared_ptr.hpp>

using namespace std;

#include <windows.h>
#include <Shlobj.h>

boost::shared_ptr<wstring> browseFolder();
boost::shared_ptr<vector<wstring>> getFilesInDirRecursiveImplementation(boost::shared_ptr<vector<wstring>> dirs, boost::shared_ptr<vector<wstring>> files);

#endif
#endif

和MacFunctions.h:

#ifndef MACTRANSFERINCLUDE
#define WACTRANSFERINCLUDE
#ifdef USE_MAC

#include <string>
#include <boost/shared_ptr.hpp>

using namespace std;

boost::shared_ptr<wstring> browseFolder();
boost::shared_ptr<vector<wstring>> getFilesInDirRecursiveImplementation(boost::shared_ptr<vector<wstring>> dirs, boost::shared_ptr<vector<wstring>> files);

#endif
#endif

WindowsFunctions.cpp已经实现,并且有效。我该怎么做Mac?我编写了一个方法来打开一个打开的对话框,但我不知道如何将数据返回到C ++中调用它的位置。

这是打开对话框的代码:

#import <Cocoa/Cocoa.h>
#include <string>

std::string* path() {
    NSOpenPanel *op = [NSOpenPanel openPanel];
    if ([op runModal] == NSOKButton) {
            NSURL *nsurl = [[op URLs] objectAtIndex:0];
            // nsurl.path contains the NSString I want to return as std::string
    }
    // ???
    return something;
}

我该怎么做,或者我是以错误的方式解决问题?

2 个答案:

答案 0 :(得分:1)

这有点啰嗦,但现在是:

std::string([[nsurl path] UTF8String]);

编辑:好的,也许不是 啰嗦。

答案 1 :(得分:0)

您有几个问题需要解决:

1)为您的C ++ API选择一个字符串类型。您的Windows版本示例使用wstring,它使用wchar_t,在Mac和许多Unix上大小为32位,但在Windows上为16位。此外,wstring用于固定大小的字符串编码,即使Windows滥用它来存储UTF16(这是一种可变长度编码)。您的Mac代码使用字符串,它使用char,在所有平台上都是1个字节。您可以在所有平台上使用UTF8,然后您可以在任何地方使用字符串。它仍然不是固定长度的(即一些字符最多可以编码为4个字节),但它在许多平台上都受支持,所有平台都可以将它们的字符串转换为UTF8。您可以在不同的平台上使用不同的字符串类型,但是您必须使用#if和#endif语句来丢弃代码,以便在每个平台上执行正确的操作。

2)从对象中获取路径。正如您在示例中的注释所述,您首先调用[nsurl path],或者在URL是相对URL的情况下安全[[nsurl absoluteURL] path]。这样你就可以得到完整的路径,而不仅仅是相对的部分。这会为您提供一个NSString对象,然后您可以请求C字符串表示。有几种方法:cString仅适用于ASCII字符串,因此不要使用它。如果您想要UTF8,请使用UTF8String。如果您需要任何其他编码(如UTF16或UTF32),您可以使用dataUsingEncoding:获取NSData对象,然后查看其字节和长度以创建字符串。

3)在使用文件路径的任何地方都要小心。文件系统有一种特殊的“规范”方式来编码文件名。这是必需的,因为Unicode对同一个角色有几种表示形式。例如。 'ä'或'¨a'。 (一种特殊的分音符,可以粘在正常的,而不是我在这里常用的那个)。因此,您需要确保将其转换为规范分解。这就是NSString的-fileSystemRepresentation所用的内容,如果你需要一个C字符串传递到采用文件路径的POSIX API(如果你使用带有NSString的Mac API,它将在透明的情况下为你做到这一点)。