I have a class which collects all paths to .txt files of a given folder and stores them into a vector. Most of the functions I use require the usage of TCHAR* to get/set current directory and so on.
The class looks like this:
typedef std::basic_string<TCHAR> tstring;
class folderManager
{
private:
TCHAR searchTemplate[MAX_PATH];
TCHAR directory[MAX_PATH];
WIN32_FIND_DATA ffd;
HANDLE hFind;
vector<tstring> folderCatalog;
vector<tstring> fileNames;
bool succeeded;
public:
// get/set methods and so on...
};
// Changed TCHAR* dir to tstring dir
void folderManager::setDirectory(tstring dir)
{
HANDLE hFind = NULL;
succeeded = false;
folderCatalog.clear();
fileNames.clear();
// Added .c_str()
SetCurrentDirectory(dir.c_str());
GetCurrentDirectoryW(MAX_PATH, directory);
TCHAR fullName[MAX_PATH];
StringCchCat(directory, MAX_PATH, L"\\");
StringCchCopy(searchTemplate, MAX_PATH, directory);
StringCchCat(searchTemplate, MAX_PATH, L"*.txt");
hFind = FindFirstFile(searchTemplate, &ffd);
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
FindClose(hFind);
return;
}
do
{
StringCchCopy(fullName, MAX_PATH, directory);
StringCchCat(fullName, MAX_PATH, ffd.cFileName);
folderCatalog.push_back(fullName);
fileNames.push_back(ffd.cFileName);
}
while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
succeeded = true;
}
This is where I need to do the conversion of System::String^ to TCHAR*
private: System::Void dienuFolderisToolStripMenuItem_Click(System::Object^
sender, System::EventArgs^ e)
{
FolderBrowserDialog^ dialog;
dialog = gcnew System::Windows::Forms::FolderBrowserDialog;
System::Windows::Forms::DialogResult result = dialog->ShowDialog();
if (result == System::Windows::Forms::DialogResult::OK)
{
// Conversion is now working.
tstring path = marshal_as<tstring>(dialog->SelectedPath);
folder->setDirectory(path);
}
}
marsha_as "Performs the marshaling on a specific data object to convert it between a managed and a native data type".
Here there is the table for possible type conversion.
I use it this way:
marshal_as<std::wstring>(value)
TCHAR can be char or wchar_t, both of them present in marshal_as specialization, I suppose you need to point TCHAR* as template parameter:
TCHAR* result = marshal_as<TCHAR*>(value)
Actually MSDN says that you have to use it this way:
#include <msclr\marshal.h>
using namespace System;
using namespace msclr::interop;
int main(array<System::String ^> ^args)
{
System::String^ managedString = gcnew System::String("Hello World!!!");
marshal_context ^ context = gcnew marshal_context();
const wchar_t* nativeString = context->marshal_as<const wchar_t*>(managedString);
//use nativeString
delete context;
return 0;
}
Related
I want to track a global variable that I am passing into an API function. I found that one could do it using a class:
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
//T operator T() const { return m_value; }
const MonitoredVariable& operator = (const T& value)
{
PlugIn::gResultOut << "value changed " << std::endl;
m_value = value;
return *this;
}
private:
T m_value;
};
The API function takes variables as
bool APIFunction(double time, bool *is_done, double *fraction_done);
The following gives me an error:
ImagePtr Im;
bool is_done;
MonitoredVariable<double*> fraction_done;
bool frameready = Im->APIFunction(2.1, is_done, fraction_done);
ERROR:
error C2664: cannot convert argument 3 from 'MonitoredVariable<double *>' to 'double *'
what would I have to change here?
thx!
I'm not really sure if this is what you want:
#include <iostream>
using namespace std;
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
//T operator T() const { return m_value; }
const MonitoredVariable& operator = (const T& value)
{
//PlugIn::gResultOut << "value changed " << std::endl;
m_value = value.m_value;
return *this;
}
void printValue() {
std::cout << m_value;
}
T& getValue() {
return m_value;
}
private:
T m_value;
};
bool func(double firstDouble, bool *is_done, double* fraction_done) {
// do stuff
*fraction_done = firstDouble + (40.23 * 5);
*is_done = true;
return true;
}
int main()
{
bool is_done = true;
MonitoredVariable<double> fraction_done;
func(2.10, &is_done, &fraction_done.getValue());
fraction_done.printValue();
return 0;
}
So basically we have a Class called MonitoredVariable which has a variable called m_value. I'm not really sure why you wanted it to be a pointer, because we can also take the address of a normal double variable.
In the following it makes perhaps more sense what I want to achieve. I want to input a class variable into an API function and monitor the variable in real time. This value goes from zero to 1 every 3 ms or so. Yet I try to avoid using while loop and track it within the class with overloaded = operator.
#include "stdafx.h"
#include <iostream>
#include <thread>
#include <future>
using namespace std;
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
void printValue() {
std::cout << m_value;
}
const MonitoredVariable& operator = (const T& value)
{
m_value = value.m_value;
if(m_value> 0.8) std::cout << m_value; // *THIS NEVER GETS PRINTED!!!*
return *this;
}
T& getValue() {
return m_value;
}
private:
T m_value;
};
bool func(bool *is_done, double* fraction_done) {
unsigned long c = 1;
while (*is_done)
{
*fraction_done = (double) 0.01*c;
this_thread::sleep_for(chrono::milliseconds(10));
c++;
if (*fraction_done >= 1) *is_done = false;
}
return true;
}
int main()
{
bool is_done = true;
MonitoredVariable<double> *MonitoredVariablePtr = new MonitoredVariable<double>();
std::future<bool> fu = std::async(std::launch::async,func, &is_done, &MonitoredVariablePtr->getValue());
// IF I UNCOMMENT THIS, IT PRINTS...
/*
while(is_done)
{
if(MonitoredVariablePtr->getValue() > 0.8) MonitoredVariablePtr->printValue();
}
*/
return 0;
}
Why does not the (if(m_value> 0.8) std::cout << m_value) line within the class never gets printed when the value is updated?
THX!
I'm using the autowrap function to interact with VBA and now I get the control using item method as below.
VARIANT result;
VariantInit(&result);
VARIANT x;
x.vt = VT_INT;
x.intVal = index;
wchar_t method[] = L"Item";
hr = AutoWrap(DISPATCH_METHOD, &result, pControls, method,1,x);
pObject = result.pdispVal;
I can get the name of the control item using this code below:
VARIANT result;
VariantInit(&result);
wchar_t method[] = L"Name";
hr = AutoWrap(DISPATCH_PROPERTYGET, &result, pObject, method, 0);
QString name=QString::fromWCharArray(result.bstrVal);
But I can't seem to find a property to get the type of object (textbox, commandbutton and etc). In VBA, there is a TypeName() function to get the type. So how can I actually do it in OLE automation autowrap function? Thanks.
Here is an example... could be optimized with a function to check the result and throw/catch an exception, but it is what it is.
#include <windows.h>
#include <atlbase.h>
#include <comdef.h>
#include <stdio.h>
int main(int argc, TCHAR* argv[])
{
class CComInit
{
public:
CComInit()
{
CoInitialize(NULL);
}
~CComInit()
{
CoUninitialize();
}
} _init;
IDispatchPtr lpDisp;
HRESULT hr = lpDisp.CreateInstance(L"Scripting.FileSystemObject");
if (FAILED(hr))
{
_com_error err(hr);
printf("Error %s\n", err.ErrorMessage());
return 0;
}
ITypeInfoPtr lpTypeInfo;
hr = lpDisp->GetTypeInfo(0, 0, &lpTypeInfo);
if (FAILED(hr))
{
_com_error err(hr);
printf("Error %s\n", err.ErrorMessage());
return 0;
}
CComBSTR ccbName, ccbDocString;
hr = lpTypeInfo->GetDocumentation(-1, &ccbName, &ccbDocString, NULL, NULL) ;
if (FAILED(hr))
{
_com_error err(hr);
printf("Error %s\n", err.ErrorMessage());
return 0;
}
printf("Type name: %S\n", ccbName.m_str);
printf("Doc: %S\n", ccbDocString.m_str);
return 0;
}
I' trying to make an identical function to "ioctl" in c++ style using boost library.
Here is my "c" style code:
int sockfd;
char * id;
struct iwreq wreq;
memset(&wreq, 0, sizeof(struct iwreq));
sprintf(wreq.ifr_name, IW_INTERFACE);
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Cannot open socket \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description is : %s\n",strerror(errno));
exit(1);
}
printf("Socket opened successfully \n");
id = malloc(IW_ESSID_MAX_SIZE+1);
wreq.u.essid.pointer = id;
if (ioctl(sockfd, SIOCGIWESSID, &wreq)) {
fprintf(stderr, "Get ESSID ioctl failed \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description : %s\n",strerror(errno));
exit(2);
}
printf("IOCTL Successfull\n");
printf("ESSID is %s\n", wreq.u.essid.pointer);
I found some relevant example, but I'm not clear how to use it correctly. example
Main function:
boost::asio::ip::udp::socket socket(io_service);
struct iwreq wreq
memset(&wreq, 0, sizeof(struct iwreq));
sprintf(wreq.ifr_name, IW_INTERFACE);
id = malloc(IW_ESSID_MAX_SIZE+1);
wreq.u.essid.pointer = id;
boost::asio::detail::io_control::myCommand command;
command.set(&wreq);
boost::system::error_code ec;
socket.io_control(command, ec);
if (ec)
{
// An error occurred.
}
Custom command:
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
namespace io_control {
// I/O control command for getting number of bytes available.
class myCommand
{
public:
// Default constructor.
myCommand()
: value_(0)
{
}
// Get the name of the IO control command.
int name() const
{
return static_cast<int>(SIOCGIWESSID);
}
// Set the value of the I/O control command.
void set(struct iwreq* value)
{
value_ = static_cast<detail::ioctl_arg_type>(value);
}
// Get the current value of the I/O control command.
std::size_t get() const
{
return static_cast<struct iwreq*>(value_);
}
// Get the address of the command data.
detail::ioctl_arg_type* data()
{
return &value_;
}
// Get the address of the command data.
const detail::ioctl_arg_type* data() const
{
return &value_;
}
private:
detail::ioctl_arg_type value_;
};
} // namespace io_control
} // namespace detail
} // namespace asio
} // namespace boost
However, the code does not work.
If you have any example code or solution, please let me know.
Thank you.
Using vc2012 express c++
I am a little confused on how a runtime library works, but I had needed to create one for a driver from some hardware I have so that it can be used in a SDK.
My source code is as follows
#include "PhantomAdapter.h"
#include <stdexcept>
int ready()
{
//return Comms::SerialPort::check();
return 1;
}
int open()
{
int flag=0;
//flag=Comms::SerialPort::openPort();
return flag;
}
int close()
{
Comms::SerialPort::closePort();
return 1;
}
int angle(double& angle)
{
angle = Comms::SerialPort::read();
return 0;
}
int torque(double torque)
{
Comms::SerialPort::send((Byte)torque);
return 1;
}
namespace Comms
{
//static p1 = gcnew System::IO::Ports::SerialPort();
int SerialPort::openPort()
{
bool check=0;
p1 = gcnew System::IO::Ports::SerialPort();
p1->BaudRate = 57600;
p1->PortName = "COM3";
if(p1->IsOpen)
return 0;
else {
p1->Open();
return 1;
}
}
int SerialPort::check()
{
array<String^>^ serialPorts = nullptr;
bool flag = true;
serialPorts = p1->GetPortNames();
for each(String^ port in serialPorts)
{
if(port=="COM3")
flag= true;
}
return flag;
}
void SerialPort::closePort()
{
p1->Close();
}
void SerialPort::send(Byte data)
{
array<unsigned char>^ buffer = gcnew array<Byte>(1);
buffer[0] = (char)data;
p1->Write(buffer,0,1);
}
double SerialPort::read()
{
double data;
data = p1->ReadByte();
return data;
}
}
header
#define PHANTOMADAPTER_API __declspec(dllexport)
#else
#define PHANTOMADAPTER_API __declspec(dllexport)
#endif
#using <mscorlib.dll>
#using <system.dll>
using namespace System;
using namespace System::IO::Ports;
using namespace System::Threading;
extern "C" {
PHANTOMADAPTER_API int ready();
PHANTOMADAPTER_API int open();
PHANTOMADAPTER_API int close();
PHANTOMADAPTER_API int angle(double& angle);
PHANTOMADAPTER_API int torque(double torque);
}
namespace Comms
{
public ref class SerialPort
{
private:
static System::IO::Ports::SerialPort^ p1;
public:
static int openPort();
static void closePort();
static double read();
static void send(Byte data);
static int check();
};
}
I am getting the following error when I call the angle DLL function or any function that requires the Comms namespace.
System.NullReferenceException: Object reference not set to an instance of an object.
at System.IO.Ports.SerialPort.get_IsOpen()
at System.IO.Ports.SerialPort.ReadByte()
at angle(Double* angle)
can someone please point me in the right direction, I feel as if the serialPort class can't be open from runtime library unless I import it somehow
The type of each codec or the type of the codec's
In the List i have in the end about 500 codec's i want that for example in the List in the beginning it will show for example:
Audio
mpeha
mpegv
.....
Video
xvid
divx
And so on.
The first two functions to get the List of codec's are in C:
const char* Encoder_GetNextCodecName()
{
current_codec = av_codec_next(current_codec);
while (current_codec != NULL)
{
return current_codec->name;
}
return "";
}
const char* Encoder_GetFirstCodecName()
{
current_codec = NULL;
return Encoder_GetNextCodecName();
}
Then i have header file:
const char* Encoder_GetNextCodecName();
const char* Encoder_GetFirstCodecName();
Then another C++ header file where i create the List:
List<String^> ^GetCodecs()
{
List<String^> ^l = gcnew List<String^>;
String ^s = gcnew String(Encoder_GetFirstCodecName());
while (!String::IsNullOrEmpty(s))
{
l->Add(s);
s = gcnew String(Encoder_GetNextCodecName());
}
return l;
}
Then when i'm doing in CSHARP this:
List<string> l = new List<string>(f.GetCodecs());
I see that the variable l containing 506 codec's .
The codec's are of ffmpeg !!!
Now in the C file there is also something like:
current_codec->type
Which have many properties.
And there is also something like this in the C file:
AVMediaType::
Which give me a 7 categories of types of the codec's.
The problem is how do i make in the C++ header file when i create the List that the List will be with the types of each codec or of each group of codec's like : Audio,Video,Data.... ?
EDIT
This is another header file i have that is connecting between the C functions and the CLI:
I have another header file where i first call the functions from C:
ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
bool Encoder_MoveToNextCodec();
bool Encoder_MoveToFirstCodec();
const char* Encoder_GetCurrentCodecName();
int Encoder_GetCurrentCodecType();
#ifdef __cplusplus
} // extern "C"
#endif
This is my CLI code:
#pragma once
// FFMPEG_WRAPPER.cpp : Defines the exported functions for the DLL application.
//
#include "ENCODER.h"
#include <stdlib.h>
#include <string.h>
#include <msclr\marshal.h>
#include <vcclr.h>
#include <cstdlib>
#include <Windows.h>
using namespace System;
using namespace System::Drawing;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Drawing::Imaging;
using namespace msclr::interop;
namespace MyVideo
{
public ref class FFMPEGWrapper
{
public:
FFMPEGWrapper(void)
{
Encoder_init();
}
ref class CodecInfo
{
public:
String^ CodecName;
int CodecType;
};
List<CodecInfo^> ^GetCodecs()
{
List<CodecInfo^> ^l = gcnew List<CodecInfo^>;
bool KeepLooping = Encoder_MoveToFirstCodec();
while (KeepLooping)
{
CodecInfo ^codec = gcnew CodecInfo();
codec->CodecName = gcnew String(Encoder_GetCurrentCodecName());
codec->CodecType = Encoder_GetCurrentCodecType();
l->Add(codec);
KeepLooping = Encoder_MoveToNextCodec();
}
return l;
}
Then in CSHARP i did:
List<f.CodecInfo> l = f.GetCodecs();
But CodecInfo is not exist and i'm getting an error on the GetCodecs()
Error 1 Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
Error 2 'ScreenVideoRecorder.Form1.f' is a 'field' but is used like a 'type'
The problems the errors are in CSHARP.
You need to expand your C code to expose the extra details you want, eg:
__declspec(thread) AVCodec* current_codec = NULL;
bool Encoder_MoveToNextCodec()
{
current_codec = av_codec_next(current_codec);
return (current_codec != NULL);
}
bool Encoder_MoveToFirstCodec()
{
current_codec = NULL;
return Encoder_MoveToNextCodec();
}
const char* Encoder_GetCurrentCodecName()
{
if (current_codec != NULL)
return current_codec->name;
return "";
}
int Encoder_GetCurrentCodecType()
{
if (current_codec != NULL)
return (int) current_codec->type;
return AVMEDIA_TYPE_UNKNOWN;
}
Then expand your CLI code to store that info:
ref class CodecInfo
{
public:
String^ CodecName;
int CodecType;
...
};
List<CodecInfo^> ^GetCodecs()
{
List<CodecInfo^> ^l = gcnew List<CodecInfo^>;
bool KeepLooping = Encoder_MoveToFirstCodec();
while (KeepLooping)
{
CodecInfo ^codec = gcnew CodecInfo();
codec->CodecName = gcnew String(Encoder_GetCurrentCodecName());
codec->CodecType = Encoder_GetCurrentCodecType();
...
l->Add(codec);
KeepLooping = Encoder_MoveToNextCodec();
}
return l;
}
Then lastly, use the new info as needed:
List<CodecInfo> l = f.GetCodecs();
foreach(CodecInfo codec in l)
{
// use codec.CodecName, codec.CodecType, ... as needed
}