
В кроссплатформенных приложениях чего только не встретишь. Или напишешь. Вот, намедни
Напомню предыдущую серию саги: грабли под Windows.
То есть у нас все тот же экзотический еж + питон = колючая проволока. На сей раз
Темный рыцарь: начало
Начиналось все так обыденно:
void FooExpFilter::ExportToStream( IPMStream* stream, IDocument* doc, IPMUnknown* targetboss, const PMString& formatName, UIFlags uiFlags) { IDFile outputFile; InterfacePtr<IFileStreamData> fileData(stream, IID_IFILESTREAMDATA); outputFile = fileData->GetSysFile(); SDKFileHelper fh(outputFile); PMString pathID = fh.GetPath(); WideString pathWID(pathID); std::string xID; StringUtils::ConvertWideStringToUTF8 (pathWID, xID);
и работало на маке и на Windows. Пока InDesign не дорос до версии CS5.5. И тут
Звездные войны: империя наносит ответный удар
В сторону: вот эти записи в лог «как бы чего не вышло» очень помогают, рекомендую. Если конечно логи с умом писать, а то (лично видел!) однажды от обилия логов получился performance degradation и «кодярник» (С) лог 40 секунд писал, а без лога полсекунды работает. Индусы постарались — написали свой log4j с блэкджеком но без буферизации.
Получаем лог от клиента, а там — Macintosh HD::Foo::Bar!
Приезжайте к нам в Простоквашино — если у вас нет бальных платьев
Быстрое гугление (как перевести карбоно-маковые пути в Unix) приводит к подробной инструкции, как переводить руками с учетом mount points. И applescript в качестве примера, что и в каком порядке у Finder спрашивать. Ага, ага — нам вот только ObjectiveC не хватало для полного счастья.
Хлебнув полведра кофе, и погрепав Adobe SDK, находим решение, достойное ithappens. Вот оно.
IDFile outputFile; InterfacePtr<IFileStreamData> fileData(stream, IID_IFILESTREAMDATA); outputFile = fileData->GetSysFile(); // URL for java PMString pathJ = FileUtils::SysFileToFileURL(outputFile); WideString pathWJ(pathJ); std::string xj; StringUtils::ConvertWideStringToUTF8 (pathWJ, xj);
и в Java появляются еще 3 строчки:
if(externFile.startsWith("file://")) { File externFd = new File(new java.net.URI(externFile)); externFile = externFd.getAbsolutePath(); }
То есть, не найдя как передать путь, мы передали… URL!
И это даже работает.
Disclaimer: не откажусь от правильного примера — как перевести карбоновые пути в Unix без ObjectiveC. Хоть и неактуально, но интересно. Если оно вообще есть, а не «отрезать голову и поменять :: на /», неправильно я и сам умею.
Игры разума: как можно было сделать лучше
Update 1: notorca навел на мысль использовать маковую CFURLCopyFileSystemPath:
void FooExpFilter::ExportToStream( IPMStream* stream, IDocument* doc, IPMUnknown* targetboss, const PMString& formatName, UIFlags uiFlags) { IDFile outputFile; InterfacePtr<IFileStreamData> fileData(stream, IID_IFILESTREAMDATA); outputFile = fileData->GetSysFile(); #ifdef WINDOWS SDKFileHelper fh(outputFile); PMString pathID = fh.GetPath(); #endif #ifdef MACINTOSH FSSpec fsSpec; PMString pathID; OSErr err = FileUtils::IDFileToFSSpec(outputFile, fsSpec); if (err == noErr) { FSRef fsRef; err = MacFileUtils::FSSpecToFSRef(fsSpec, fsRef); if (err == noErr) { CFURLRef appURL = ::CFURLCreateFromFSRef(NULL, &fsRef); CFStringRef app_str = ::CFURLCopyFileSystemPath(appURL, kCFURLPOSIXPathStyle); if (app_str) { pathID.SetCFString(app_str); ::CFRelease(app_str); } if (appURL) ::CFRelease(appURL); } } #endif WideString pathWID(pathID); std::string xID; StringUtils::ConvertWideStringToUTF8 (pathWID, xID);
Update 2: А strizh дал еще одну подсказку — можно было использовать FileUtils::FileURLToPosixPath, в этом случае код становится таким:
IDFile outputFile; InterfacePtr<IFileStreamData> fileData(stream, IID_IFILESTREAMDATA); outputFile = fileData->GetSysFile(); #ifdef WINDOWS SDKFileHelper fh(outputFile); PMString pathID = fh.GetPath(); WideString pathWID(pathID); std::string xfinal; StringUtils::ConvertWideStringToUTF8 (pathWID, xfinal); #endif #ifdef MACINTOSH PMString pathJ = FileUtils::SysFileToFileURL(outputFile); WideString pathWJ(pathJ); std::string xj; StringUtils::ConvertWideStringToUTF8 (pathWJ, xj); std::string xfinal = FileUtils::FileURLToPosixPath(xj); #endif
Так что если через URL — то варианты есть. Без перехода path -> URL -> posix path пока подсказок не поступало (нет, я все еще не согласен тащить с собой кусок на ObjectiveC).