I use Process::Start function to run an .exe from another program.
I 'm thinking storing the .exe in location where main program (vc++) is stored. That way I could via GetCurrentDir get always the location of .exe too and then import location in Process::Start, as a variable. Is this possible?
GetCurrentDir:
#include <stdio.h> /* defines FILENAME_MAX */
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
return errno;
}
Location is stored in cCurrentPath variable. I tried with:
Process::Start("%s\\application.exe", cCurrentPath);
but didn't work out. How can I fix this?
Related
I was trying to find a simple way to redirect std::cout outputs to the Visual Studio console window, so that the same code can be used to log on Mac and Windows.
After an hour of searching, I finally found a simple way that works (mostly based on https://stackoverflow.com/a/51498216/3311183)
At the start of my program, I put:
#ifdef _WIN32
#include <ostream>
#include <Windows.h>
#include <string>
#include <sstream>
#endif
And then at the start of any function that I want to redirect std::cout in (i.e. at the top of my main function), I put:
#ifdef _WIN32
std::streambuf* backup;
backup = std::cout.rdbuf();
std::stringstream ss;
std::cout.rdbuf(ss.rdbuf());
#endif
Then, at the bottom of that function (i.e. at the end of my program), I put:
#ifdef _WIN32
OutputDebugString(ss.str().c_str());
std::cout.rdbuf(backup);
#endif
That's it!
When I add winsock2 to my MinGW-w64 C/C++ project, it then gets make error:
undefined reference to `InitializeConditionVariable'.
NOTE: InitializeConditionVariable built and ran ok prior to adding Winsock.
main.c ...
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include "infrastructure.h"
#include "common.h"
#include "bg.h"
#include "aox.h"
#include <windows.h>
#include <ws2tcpip.h>
#include <synchapi.h>
. . .
static void mutexInit()
{
#ifdef WINDOWS
// Initialize critical sections and condition variables
InitializeCriticalSection(&iqSamplesCriticalSection);
InitializeCriticalSection(&bgBufferCriticalSection);
InitializeConditionVariable(&newSamplesAvailable); <<<<<<<<<<<<<<<<<<< ERROR: undefined reference
#else
// Initialize mutexes
pthread_mutex_init(&iqSamplesCriticalSection, NULL);
pthread_mutex_init(&bgBufferCriticalSection, NULL);
pthread_cond_init(&newSamplesAvailable,NULL);
#endif
}
InitializeConditionVariable() has nothing to do with WinSock. This is strictly an issue with your own code.
InitializeConditionVariable() was introduced in Windows Vista. You are likely just linking to an out-dated kernel32.lib that doesn't expose newer Vista+ APIs. So, you can either:
update the Windows SDK for your compiler.
load the various ConditionVariable functions dynamically at runtime using GetProcAddress().
I have a small snipped of code, which just produces a function to get the current directory for either Windows or Linux platform:
#include <stdio.h> /* defines FILENAME_MAX */
#include <string>
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
std::string getcwd(){
char mCurrentPath[FILENAME_MAX];
GetCurrentDir(mCurrentPath, sizeof(mCurrentPath));
return *(new std::string (mCurrentPath));
}
This is all great and working; however, I'd like to make the getcwd() function inside the namespace, fUtils, hence I did this:
#include <stdio.h> /* defines FILENAME_MAX */
#include <string>
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
namespace fUtils{
std::string getcwd(){
char mCurrentPath[FILENAME_MAX];
GetCurrentDir(mCurrentPath, sizeof(mCurrentPath));
return *(new std::string (mCurrentPath));
}
}
But this gives an error in VSCode which says:
no matching function for call to 'getcwd'
What mistake am I making in this? If this isn't how I put the function to the namespace fUtils, then how should I put it into the namespace?
Your fUtils::getcwd() function is attempting to call itself when the GetCurrentDir macro is evaluated (to getcwd), and this results in a function that expects no argument but is being given two arguments.
To resolve this, add the global namespace operator (::) in the definitions for GetCurrentDir, as follows:
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir ::_getcwd
#else
#include <unistd.h>
#define GetCurrentDir ::getcwd
#endif
Then, in your function body, it is clear to the compiler that your aren't looking for a 'recursive' (and invalid) call.
Use of macros in such context is invitation to problems in future.
Just wrap those functions with own API and all problems will be resolved.
Header file:
#include <string>
namepsace fUtils {
std::string getcwd();
}
Then you can have platform specific cpp files, Windows:
namepsace fUtils {
std::string getcwd() {
char mCurrentPath[FILENAME_MAX];
::_getcwd(mCurrentPath, sizeof(mCurrentPath));
return {mCurrentPath};
}
}
Mac version is obvious.
You also can use this macros inside single cpp file and this way contain them there if you do not what to do larger clean up.
Side notes:
there is boost::filesystem which has such api also use of boost::filesystem::path is quite handy
C++17 introduces std::filesystem, but it is not well supported yet (for example MacOS)
if you wrap this functionality in classes you will open your way for better testing (mocks).
I have a dll and header file. Now I am creating a console application using vs2015. and load this library. But while getting GetProcAddress of function. It is always returning NULL. Here is my code.
Contents of header file (test.h) (This header file is only for your reference)
#ifdef APPLYDLL_EXPORTS
#define APPLYDLL_API __declspec(dllexport)
#else
#ifdef BUILD_EXE
#define APPLYDLL_API
#else
#define APPLYDLL_API __declspec(dllimport)
#endif
#endif
#include <string>
#include <winerror.h>
APPLYDLL_API HRESULT ApplySettings(std::string input);
Contents of console application (cpp file)
#include "stdafx.h"
#include <Windows.h>
#include <string>
using namespace std;
//Define the function prototype
typedef HRESULT(CALLBACK* ApplySettings)(std::string);
int main()
{
HINSTANCE hLib = LoadLibrary(TEXT("ApplyTool.dll"));
if (NULL != hLib)
{
//Get pointer to our function using GetProcAddress:
ApplySettings applySettings = (ApplySettings)GetProcAddress(hLib,"ApplySettings");
DWORD errorcode=GetLastError(); //errorcode 127, Procedure not Found
}
return 0;
}
I don't know, Where I am doing silly mistake.
Someone please help me.
Thanks in adv.
I Agree with CrazyCoder, check the DLL using Dependency Walker with that function name.
and try to change define as like below,
#define APPLYDLL_API __declspec(dllexport)
to
#define APPLYDLL_API extern "C" __declspec( dllexport )
Thanks, Jake.
I try to have a simple function which returns the current directory as a string:
Utils.h contains :
#ifndef __UTILS__
#define __UTILS__
#pragma once
#include <string>
#include <stdio.h> /* defines FILENAME_MAX */
#ifdef __linux__
#include <unistd.h>
#define GetCurrentDir getcwd
#else
#include <direct.h>
#define GetCurrentDir _getcwd
#endif
namespace
{
extern std::string _getCurrentDirectory()
{
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
return "";
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
return std::string(cCurrentPath);
}
}
#endif // __UTILS__
Despite extern declaration (redundant ?) and the creation of this specified Utils.h file, I still have linking problem:
Error 2 error LNK2005: "char * __cdecl getCurrentDirectory(void)" (?getCurrentDirectory##YAPADXZ) already defined in MyLibrary.lib(myobj.obj)
Error 3 error LNK1169: one or more multiply defined symbols found
This problem appears twice, and MyLibrary.lib doesn't even use or includes Utils.h
I really don't understand despite of the time I spent on it.
Does anyone have an idea ?
Thanks