Hi All,
So I'm assuming that this is just a sandbox violation issue, that alchemy just plain blocks local file system access by anything that isn't an AS3 object capable of doing so (such as the file class.) I'd just like to get a solid confirmation from an employee or someone else who can give me a confirmation on this. Basically here's what I'm doing in C++
//Get the file class
flash_filesystem_namespace = AS3_String("flash.filesystem");
File_class = AS3_NSGetS(flash_filesystem_namespace, "File");
AS3_Val fileObject = AS3_New(File_class, emptyParams);
//
//Get the bytearray class
flash_utils_namespace = AS3_String("flash.utils");
ByteArray_class = AS3_NSGetS(flash_utils_namespace, "ByteArray");
AS3_Val byteArray = AS3_New(ByteArray_class, emptyParams);
//
AS3_SetS(fileObject, "nativePath", AS3_String(fileOne.c_str())); /// ------ fileOne is of type string and I'm passing it in as an arg
AS3_Val doesFileRefExist = AS3_GetS(fileObject, "exists");
if(doesFileRefExist == AS3_False()){
AS3_Call(actionscriptCallbackFunction, parentClass, AS3_Array("StrType", "File Does Not Exist"));
}
if(doesFileRefExist == AS3_True()){
fileObject = AS3_CallS("resolvePath", parentClass, AS3_Array("StrType", fileOne.c_str())); ---This works
}
So that works if I import and use a flash.filesystem.File object to check and see if the file exists locally. However this doesn't work:
bool doesFileExist(string* fName)
{
bool exists = false;
string tmpfName = *fName;
fstream fileToCheck;
fileToCheck.open(tmpfName.c_str(),ios::in);
if( fileToCheck.is_open() )
{
exists=true;
}
fileToCheck.close();
return exists;
}
My function to check and see if the file exists always returns false, static of course the file doesn't exist. I've compiled this project into an executable before so I can verify that it's not my code.
It's also important to note that I'm compiling this into an AIR 2.5 project, so I assumed that my compiled C++ code would inherit the same permissions (local file io). Any clarification/confirmation on this would be great and thanks in advance.
I found this article:
http://blogs.adobe.com/cssdk/2010/05/leveraging_cc_libraries_in_the_cs _sdk_using_alchemy.html
Specifically, it mentions the following:
//==================================================================== =========================================
In most Alchemy use cases, all we have to do is initialize the C library and then call into the interfaces we defined:
var loader:CLibInit = new CLibInit();
var lib:Object = loader.init();
lib.setup();
However, it’s slightly more complex in our case. Alchemy requires that you pass any files needed by the C code as a byte array to the loader before calling your interfaces. Because the C code requires access to the file system (to read the dictionary, grammar rules, etc.), we’re going to need a function something like this:
private function supplyFile( loader:CLibInit, file:File, fileName:String):void {
var bytes:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
stream.readBytes(bytes, 0, stream.bytesAvailable);
stream.close();
loader.supplyFile(fileName, bytes);}
And that’s all there is to it. To compile the CS Extension, generate the swc and copy it into the libs/ folder. At runtime, make sure you have the contents of Link Grammar’s data/ folder (which includes 4.0.dict, words/, etc.) copied onto the desktop.
//==================================================================== =========================================
Can anyone comment on or add to this?
Okay so after doing some digging, here it is:
http://labs.adobe.com/wiki/index.php/Alchemy:Documentation:Developing_ with_Alchemy:AS3_API
Near the top of the page, you can see a description of the supplyFile method. However, I learned through experimenting and reading around other blogs that when you pass in the "path" of the file to alchemy, coupled with a bytearray of the file, the "path" is really just a unique identifier for that newly created byte array inside of alchemy/your c/c++ code.
I just want to say that I really hope the alchemy project stays alive, and also that I believe work should be done to permit local file system access directly through c/c++ using ifstream/fopen ect, not through virtualization. I don't understand why the alchemy code doesn't automatically inherit all sandbox restrictions and permissions from the parent application sandbox but like I said, I hope it's something we'll see in the future.
I hope this also may be helpful to other people with similar questions.
Just an update for people who want to know an easier way of doing this, heres some code for passing bytearray to C++ and passing back a pointer to the modified data in C++ to flash, then saving that modified data from alchemy memory to the file system. It's very fast and other tutorials I've seen say it's the fastest method:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.utils.ByteArray;
import cmodule.MyAlchemyLib.CLibInit;
import cmodule.MyAlchemyLib.gstate;
public class MyAlchemyLibMain extends MovieClip
{
private var lib:Object;
private var loader:CLibInit;
private var file:File;
private var dataLength:int;
private var sysMem:ByteArray;
public function ScramblrAlchemyMain()
{
loader = new CLibInit;
file = File.desktopDirectory;
file.addEventListener(Event.SELECT, getFile);
file.browseForOpen("Find file to load.");
}
private function getFile(e:Event):void
{
file = e.target as File;
lib = loader.init();
file.addEventListener(Event.COMPLETE, fileLoadedLocally);
file.load();
}
private function fileLoadedLocally(e:Event):void
{
trace("Data length: " + file.data.length);
dataLength = file.data.length;
var fileData:ByteArray = file.data;
sysMem = gstate.ds;
lib.processBytes(fileData, dataLength, "My string data", -1, alchemyCallback, this);
}
public function alchemyCallback(pointerRef:int):void
{
trace("Alchemy called me back baby!")
trace("Bytes are at: " + pointerRef);
var alchemyBytes:ByteArray = new ByteArray();
aalchemyBytes.writeBytes(sysMem, pointerRef, dataLength);
trace(alchemyBytes.length);
var sf:File = File.desktopDirectory;
sf = sf.resolvePath(file.parent.nativePath);
sf = sf.resolvePath("Modded File.f");
trace(sf.nativePath);
var fs:FileStream = new FileStream();
fs.open(sf, FileMode.WRITE);
fs.writeBytes(alchemyBytes, 0, alchemyBytes.length);
fs.close();
fs = null;
}
}
}
North America
Europe, Middle East and Africa
Asia Pacific