I'm writing a tool that makes use of gccxml. Basically I'm parsing the output xml file that has been created by gccxml. This works great on my windows machine in visual studio except for a couple of drawbacks. Here's the current state of my project:
cmake_gui gave me a visual studio solution that compiles perfectly (x64 Release). It's set up to create three executables in E:\cmake_builds\GCCXML\bin\Release.
My own C++ tool is located in a different VS solution file. When it's supposed to make use of gccxml the following code is used:
bool Parser::ParseFile( const std::string& _szFileName, std::string& _gccxmlPath,
const std::string& _tempFileLocation,
std::string& _errorStr)
{
bool retVal = true;
printf("Parsing file %s...\n\n", _szFileName.c_str());
/* format _gccxmlPath, adding a final forward slash to the path if required */
char lastChar = _gccxmlPath.at(_gccxmlPath.length()-1);
if(lastChar != '/' && lastChar != '\\')
_gccxmlPath += "/";
/* set up a temporary environment path variable so that the gccxml exe files may locate each other */
char envPath[500];
sprintf_s(envPath, "PATH=%s", _gccxmlPath.c_str());
const char* gccxml_env[] =
{
/* set path to gccxml directory where all exe files from gccxml are located */
envPath,
0
};
/* path & filename of gccxml.exe */
char gccxml_exe[500];
sprintf_s(gccxml_exe, "%sgccxml.exe", _gccxmlPath.c_str());
/* parameter string used to set gccxml output filename */
char fxmlParam[500];
sprintf_s(fxmlParam, "-fxml=\"%s\"", _tempFileLocation.c_str());
/* synthesize argument list for gccxml*/
/* see: http://gccxml.github.io/HTML/Running.html */
/* and: https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Invoking-GCC.html */
const char* gccxml_args[GCCXML_PARAM_LEN];
unsigned int curPos = 0;
/* 1st argument: exe name */
gccxml_args[curPos++] = "gccxml.exe";
/* the source code to be compiled */
gccxml_args[curPos++] = _szFileName.c_str();
/* try to find out which msvc compiler to use */
gccxml_args[curPos++] = "--gccxml-compiler cl";
/* the output xml file */
gccxml_args[curPos++] = fxmlParam;
/* last argument: zero termination */
gccxml_args[curPos++] = 0;
/* call gccxml & compile the source code file */
if(0 != _spawnvpe(P_WAIT, gccxml_exe, gccxml_args, gccxml_env))
{
_errorStr += "GCCXML Compiler Error";
return false;
}
/* now parse the gccxml output file from tempfile ... */
...
...
return retVal;
}
as you can see I have to set up a local environment PATH variable to make sure the three executables are able to find each other.
This works great for what I want to do.
Unfortunately I can't use this method to call gccxml.exe when I move the three executables to a different directory. Of course I provide the new _gccxmlPath string but gccxml returns
"Support item Vc10/Include is not available..."
telling me that it looked in the folder into which I moved the executables. All my local copies of Vc10/Include however are located somewhere totally different and I don't understand how it had been able find one of these before I moved the executables.
It seems like this problem can be fixed by calling gccxml_vcconfig.exe using the parameters "patch_dir" and providing the directory "gccxml/Source/GCC_XML/VcInstall" from my gccxml source files. I'm, however, not able to solve my issue this way using any of the spawn* commands.
If I do the gccxml_vcconfig.exe runs just fine but after that I'm trying to call gccxml.exe and it turns out that it still looks in the same directory as before.
So gccxml_vcconfig.exe was probably not what I was looking for?
I'm trying to find a way to provide my tool to users who don't want to recompile gccxml on their machine so I'd like to distribute the thre binaries (and what else is needed).
just to let you know. I found a way of doing what I wanted to do. The trick is as follows:
right before vpe-spawning gccxml using its own location as environment (as shown above) vp-spawn the gccxml_vcconfig.exe without providing any environment path variables. This may look like this
std::string VcInstallDir = resolveRelativePath(_gccxmlPath + "../share/gccxml-0.9/VcInstall");
std::string GCCXML09Dir = resolveRelativePath(_gccxmlPath + "../share/gccxml-0.9");
std::vector<const char*> gccxml_config_args;
gccxml_config_args.push_back("gccxml_vcconfig.exe");
gccxml_config_args.push_back(VcInstallDir.c_str());
gccxml_config_args.push_back(GCCXML09Dir.c_str());
gccxml_config_args.push_back(0);
if(0 != _spawnvp(_P_WAIT, gccxml_vcconfig_exe.c_str(), gccxml_config_args.data()))
{
_errorStr += "GCCXML Configuration Error";
return false;
}
note that resolveRelativePath is a self written function for string manipulation that produces a valid absolute path; gccxml_vcconfig_exe contains the absolute path to my exe file
and I somewhat changed my coding style from arrays to std::vectors as you can see
Related
How can I read the content of boost::interprocess::file_handle_t?
We are currently prototyping with code found at scoped_lock doesn't work on file?. This demonstrates how to write but we would also like to read from the file. How can this be accomplished? Done the normal google search and looked at boost docs and header files without any luck. Appreciate any input.
#include "boost/format.hpp"
#include "boost/interprocess/detail/os_file_functions.hpp"
namespace ip = boost::interprocess;
namespace ipc = boost::interprocess::detail;
void fileLocking_withHandle()
{
static const string filename = "fileLocking_withHandle.txt";
// Get file handle
boost::interprocess::file_handle_t pFile = ipc::create_or_open_file(filename.c_str(), ip::read_write);
if ((pFile == 0 || pFile == ipc::invalid_file()))
{
throw runtime_error(boost::str(boost::format("File Writer fail to open output file: %1%") % filename).c_str());
}
// Lock file
ipc::acquire_file_lock(pFile);
// Move writing pointer to the end of the file
ipc::set_file_pointer(pFile, 0, ip::file_end);
// Write in file
ipc::write_file(pFile, (const void*)("bla"), 3);
// Unlock file
ipc::release_file_lock(pFile);
// Close file
ipc::close_file(pFile);
}
We are developing on Windows and Linux.
To solve the issue we used platform specific method.
So for Windows platform we used ReadFile(..) [#include "Windows"] and for Linux we used read(..) [#include
I have the following code that tries to read a INI file from a given location and if it fails it then tries to open in the current directory. My application has these two modes of execution, MAM and No MAM, hence the variable names.
{
const char section[]="CONFIG";
const char key[]="HEAP";
char value[16];
const char pwcfgFileMam[]="..\\pwcfg.ini";
const char * const pwcfgFileNoMam = pwcfgFileMam + 1;
long rc;
DWORD rcProfile;
value[0] = '\0';
rcProfile= GetPrivateProfileString( section, key, "", value,
sizeof(value)-1, pwcfgFileMam );
if ( 0 == rcProfile )
{
rcProfile = GetPrivateProfileString( section, key, "", value,
sizeof(value)-1, pwcfgFileNoMam );
}
// DO_SOMETHING(value);
}
According to the official documentation, the function should work only with full paths which is another name for absolute paths, but this snippet work as long as you put a .\ or ..\ prefix on the path. I previously had a bug in the 6th line, it was coded like this:
const char * const pwcfgFileNoMam = pwcfgFileMam + 3;
So, the function cannot work probably with only filenames, it needs at least a . or .. to "find" the file. My boss told me that the function runs in another process or context or something, and thus it needs the "path" to force this other context to query the requirer for its current working directory. Anyone has a more throughly answer on why this function behaves like this? Is this just the case of a badly implemented and badly documented API?
Oh, by the way, I'm compiling this code with Visual Studio 2008 on a Windows 7 machine.
I am trying to delete all the temporary files created by my application during uninstall. I use the following code:
bool DeleteFileNow( QString filenameStr )
{
wchar_t* filename;
filenameStr.toWCharArray(filename);
QFileInfo info(filenameStr);
// don't do anything if the file doesn't exist!
if (!info.exists())
return false;
// determine the path in which to store the temp filename
wchar_t* path;
info.absolutePath().toWCharArray(path);
TRACE( "Generating temporary name" );
// generate a guaranteed to be unique temporary filename to house the pending delete
wchar_t tempname[MAX_PATH];
if (!GetTempFileNameW(path, L".xX", 0, tempname))
return false;
TRACE( "Moving real file name to dummy" );
// move the real file to the dummy filename
if (!MoveFileExW(filename, tempname, MOVEFILE_REPLACE_EXISTING))
{
// clean up the temp file
DeleteFileW(tempname);
return false;
}
TRACE( "Queueing the OS" );
// queue the deletion (the OS will delete it when all handles (ours or other processes) close)
return DeleteFileW(tempname) != FALSE;
}
My application is crashing. I think its due to some missing windows dll for the operations performed. Is there any other way to perform the same operation using Qt alone?
Roku have already told your problem in manipulating with QString and wchar_t*.
See the documentation: QString Class Reference, method toWCharArray:
int QString::toWCharArray ( wchar_t * array ) const
Fills the array with the data contained in this QString object. The array is encoded in utf16 on platforms where wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms where wchar_t is 4 bytes wide (most Unix systems).
array has to be allocated by the caller and contain enough space to hold the complete string (allocating the array with the same length as the string is always sufficient).
returns the actual length of the string in array.
If you are simply looking for a way to remove a file using Qt, use QFile::remove:
QFile file(fileNameStr);
file.remove(); // Returns a bool; true if successful
If you want Qt to manage the entire life cycle of a temporary file for you, take a look at QTemporaryFile:
QTemporaryFile tempFile(fileName);
if (tempFile.open())
{
// Do stuff with file here
}
// When tempFile falls out of scope, it is automatically deleted.
Is there any way to postprocess a DLL and its .lib file to remove symbols that I do not want within them?
Background:
The DLL's code uses boost::serialization, which dllexports (many many) symbols. Apparently this is so as to cause the linker not to omit static objects that are unreferenced but have important side effects when initialized.
However, I'd very much prefer that there be no hint of boost within the DLL's exported symbols.
I reason that since the link step has completed that it would be safe to remove the mess in the symbol table caused by the library.
Hence, I am wondering if there exists some tool to accomplish this.
I don't know a tool that does this, but here is a piece of C++ code you can build that can change a DLL exported names. In this case, you can set the names you don't want to an empty string (the 0 character):
void RemoveUnwantedExports(PSTR ImageName)
{
LOADED_IMAGE image;
// load dll in memory for r/w access
// you'll need Imagehlp.h and Imagehlp.lib to compile successfully
if (MapAndLoad(ImageName, NULL, &image, TRUE, FALSE))
{
// get the export table
ULONG size;
PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(image.MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
PIMAGE_SECTION_HEADER *pHeader = new PIMAGE_SECTION_HEADER();
// get the names address
PULONG names = (PULONG)ImageRvaToVa(image.FileHeader, image.MappedAddress, exports->AddressOfNames, pHeader);
for (ULONG i = 0; i < exports->NumberOfNames; i++)
{
// get a given name
PSTR name = (PSTR)ImageRvaToVa(image.FileHeader, image.MappedAddress, names[i] , pHeader);
// printf("%s\n", name); // debug info
if (IsUnwanted(name))
{
name[0] = 0; // set it to an empty string
}
}
UnMapAndLoad(&image); // commit & write
}
}
BOOL IsUnwanted(PSTR name)
{
// implement this
}
It's more some kind of obfuscation but removing names completely is more complex since it requires a full consistent rewrite of the exports section.
What are the Win32 APIs to use to programically delete files and folders?
Edit
DeleteFile and RemoveDirectory are what I was looking for.
However, for this project I ended up using SHFileOperation.
I found the sample code at CodeGuru helpful.
There are two ways to approach this. One is through the File Services (using commands such as DeleteFile and RemoveDirectory) and the other is through the Windows Shell (using SHFileOperation). The latter is recommended if you want to delete non-empty directories or if you want explorer style feedback (progress dialogs with flying files, for example). The quickest way of doing this is to create a SHFILEOPSTRUCT, initialise it and call SHFileOperation, thus:
void silently_remove_directory(LPCTSTR dir) // Fully qualified name of the directory being deleted, without trailing backslash
{
SHFILEOPSTRUCT file_op = {
NULL,
FO_DELETE,
dir,
"",
FOF_NOCONFIRMATION |
FOF_NOERRORUI |
FOF_SILENT,
false,
0,
"" };
SHFileOperation(&file_op);
}
This silently deletes the entire directory. You can add feedback and prompts by varying the SHFILEOPSTRUCT initialisation - do read up on it.
I think you want DeleteFile and RemoveDirectory
See uvgroovy's comment above. You need 2 nulls at the end of the 'dir' field.
int silently_remove_directory(LPCTSTR dir) // Fully qualified name of the directory being deleted, without trailing backslash
{
int len = strlen(dir) + 2; // required to set 2 nulls at end of argument to SHFileOperation.
char* tempdir = (char*) malloc(len);
memset(tempdir,0,len);
strcpy(tempdir,dir);
SHFILEOPSTRUCT file_op = {
NULL,
FO_DELETE,
tempdir,
NULL,
FOF_NOCONFIRMATION |
FOF_NOERRORUI |
FOF_SILENT,
false,
0,
"" };
int ret = SHFileOperation(&file_op);
free(tempdir);
return ret; // returns 0 on success, non zero on failure.
}
I believe DeleteFile does not send the file to the Recycle Bin. Also, RemoveDirectory removes only empty dirs. SHFileOperation would give you the most control over what and how to delete and would show the standard Windows UI dialog boxes (e.g. "Preparing to delete etc.) if needed.
/* function used to send files and folder to recycle bin in win32 */
int fn_Send_Item_To_RecycleBin(TCHAR newpath[])
{
_tcscat_s(newpath, MAX_PATH,_T("|"));
TCHAR* Lastptr = _tcsrchr(newpath, _T('|'));
*Lastptr = _T('\0'); // Replace last pointer with Null for double null termination
SHFILEOPSTRUCT shFileStruct;
ZeroMemory(&shFileStruct,sizeof(shFileStruct));
shFileStruct.hwnd=NULL;
shFileStruct.wFunc= FO_DELETE;
shFileStruct.pFrom= newpath;
shFileStruct.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
return SHFileOperation(&shFileStruct);
}
For C++ programming, if you're willing to work with third-party libraries,
boost::filesystem::remove_all(yourPath)
is much simpler than SHFileOperation.