I have two custom protobuf libraries. One is dynamic, other is static.
Static lib has a message:
message DataType
{
int number = 1;
string name_1 = 2;
string name_2 = 3;
string name_3 = 4;
}
// The dynamic lib has a message:
message MyMessage
{
DataType type = 1;
}
I build dynamic proto lib with linking static proto lib to it.
Then I build exe application to which I link dynamic proto lib.
The problem is that when I set one of name_1, name_2 or name_3, they all have this value. I think all these strings have same buffer.
If to convert dynamic lib to static, then problem disappears.
Could anyone explain me what is wrong with it? Thank you.
If a field is not set then it should return empty string. Please check the documentation here.
If you are using version 2 you can query whether the field is set by has_name_x().
By the way there are several ways to set a value:
The simplest creates a copy: void set_name_x(const string& value)
In case of C++11 you can move a string value: void set_name_x(string&& value)
You can pass pointer: void set_allocated_name_x(string* value)
You can get the pointer to the stored string: string* mutable_name_x()
I would advice to get familiar with protobuf and let it manage memory and use set_name_x. If it is not sufficient you can optimize your code with manual memory management.
Related
I'm working on a proprietary code base, so I have to abstract this.
I'm trying to set the value of DataType_T*** myData in MyApplication. I'm using a shared c++ library (which I denote library A) to set the value. The shared c++ library is just a simple wrapper class around a C API.The C API is included in library A as a shared library (which I denote library B).
So MyApplication calls GetData(myData) in A which calls GetData(myData) in B.
MyApplication has the following code:
void OnButtonPress(){
const DataType*** myData;
GetData(myData);
DataTypeVal1 val1 = (*myData)[0]->val1; // just grabbing some info.
}
GetData(myData): works, and properly sets myData.
Me: types some new code
void OnButtonPress(){
const DataType*** myData;
GetData(myData);
const void* strData = (*myData)[0]->strData; // just grabbing some info now that we have the pointer.
//Add lots more new code that does this over and over for each member of myData
String^ str = gcnew String(static_cast<const char*>(strData));
}
GetData(myData): throws a write access violation.
Me: ". . . . . . .what."
Could the exception be getting thrown because of some sort of dll unloading?
Is there a possibility that the linking process changes when I type new code?
I haven't encountered an issue like this before, so I don't really know how to debug this.
Got suggestions?
Thanks.
Solved.
I found my undefined behavior.
I think you want something like this:
const DataType** myData;
GetData(&myData);
const void* strData = myData[0]->strData;
Because in the original code you're just passing a pointer by value; an uninitialized pointer, and then accessing that same uninitialized value.
ed: fixed up the third line
I am trying to build a memoryHandler which allows me to create and manage my shared memory, e.g. I want to create a managed_memory_object only once.
When I construct an segment I want to actually store the return pointer as a member variable in my class, so I can access it without using the find function from boost.
Is there any way to achieve something like this or do I always have to map my shared memory and find my segment with the find function?
thank you for you help
Manu
Example Class:
MemHandler::MemHandler(const char* name_p)
{
size_m = 1024;
name_m = name_p;
shm_m{open_or_create, name_m, size_m};
sharedVar_m = shm_m.construct<int>("sharedValue")(4711);
}
int* MemHandler::getSharedVar()
{
return sharedVar_m;
}
void MemHandler::setSharedVar(int value)
{
sharedVar_m = shm_m.construct<int>("sharedValue")(value);
}
I have a DLL that I need to handle in C++. I'm using WxWidgets (standard compilation, but I also tried Unicode on/off) and NetBeans. I also tried dealing with this without WxWidgets (windows.h) and had same problems.
Here is how I access the DLL functions using WxWidgets:
// -------------------- POINTERS TO FUNCTIONS
typedef bool(*TYPE_DLL_SetLicense)(char*, char*);
typedef bool(*TYPE_DLL_PingConnection)(char*);
typedef char*(*TYPE_DLL_ERR_DESCRIPTION)(void);
class DLL_Library
{
public:
// pointers to functions inside dll
TYPE_DLL_SetLicense DLL_SetLicense; //initialize - will wor fine as it returns only true/false (buffer only provide data)
TYPE_DLL_PingConnection DLL_PingConnection; //ping to serwer. Will return trahs, becouse it uses buffer to provide data ang get answear back
TYPE_DLL_ERR_DESCRIPTION DLL_ERR_DESCRIPTION; //error description. No buffer, no trouble. Returns correct string.
wxDynamicLibrary dynLib2;
int initialize(void)
{
//patch to dll
wxString path = wxStandardPaths::Get().GetExecutablePath().BeforeLast('\\') + _("\\DLL_dll\\DLLMOK.dll");
if(!wxFile::Exists(path)) return -1;
//load dll
if(!dynLib2.Load(path)) return -2;
//Assign functions in dll to variable
DLL_SetLicense=(TYPE_DLL_SetLicense) dynLib2.GetSymbol(wxT("DLL_SetLicense"));
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
DLL_ERR_DESCRIPTION=(TYPE_DLL_ERR_DESCRIPTION) dynLib2.GetSymbol(wxT("DLL_ERROR_DESCRIPTION"));
return 0;
}
};
And here is the function I run. It should return and XML content, that I try to save to the file.
//DLL_PingConnection
//result ping to be save in file
wxFile file_ping_xml;
plik_ping_xml.Open(wxT("C:\\dll\\ping.xml"),wxFile::write);
char buffor_ping_xml[2000];
//I run the function here
bool is_ping = DLL_PingConnection(buffor_ping_xml);
if(is_ping)
{
tex_box->AppendText(wxT("DLL_PingConnection True\n"));
//we save result to file
bool is_write_ping_ok = file_ping_xml.Write(buffor_ping_xml,2000);
if (is_write_ping_ok){tex_box->AppendText(wxT("Save to file is ok ok\n"));}
else {tex_box->AppendText(wxT("Save to file failed :( \n"));}
}
else
{
tex_box->AppendText(wxT("DLL_PingConnection False\n"));
}
std::cout << "Error description: " << DLL_ERR_DESCRIPTION() << "\n"; //will work fine both in saving to file, and in streaming to screen.
The problem is that inside the file instead of good content I get rubbish like this:
NOTE that this only happens in functions that use buffers like:
char buffer[2000] //buffer will contain for example file xml
function do_sth_with_xml(buffer) //buffer containing xml will (should) be overwriten with xml results of the function - in our case DLL_PingCONNECTION should save in buffer xml with connection data
Documentation say that the DLL operates on Windows-1250. File ping.xml I have set to windows ANSI, but I don't think problem lies here.
EDIT: I have written problem without WxWidgets (I load DLL using windows.h) - same problems. Here is the code: Getting trash data in char* while using it as buffer in function . Please help :(
This
DLL_PingConnection=(TYPE_DLL_PingConnection)
shouldn't it be
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
?
seems otherwise you will not get a valid pointer to the function in the DLL.
as a general rule you should check return values, especially from a DLL
you load dynamically since it happens that you sometimes get another version
of the DLL which may have a function with same name but other signature or
where is missing entirely.
You named a function
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(....
and call it with
OSOZ.OSOZ_PingConnection(buffor_ping_xml);
you typedef a function
typedef bool(*TYPE_DLL_PingConnection)(char*);
you create a variable
char buffor_ping_xml[2000];
in your typedef it is char* and your buffor_ping_xml is char
how can that work ?
try
char *buffor_ping_xml = new char[2000];
/* or */
wchar_t *buffor_ping_xml = new wchar_t[2000];
/* or */
wxChar *buffor_ping_xml = new wxchar[2000];
bool is_ping = DLL_PingConnection(buffor_ping_xml);
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
write mystring to file.
To Do:
look in your wxwidgets\libs folder for your libs
are there libwxmsw29ud_* with a 'u' in the name (after version number here 29)?
If not You can not use unicode
If yes next steps
for all different test char *, wchar_t *, wxChar * give the files different name.
for example file_ping_xml.Open(wxT("C:\dll\ping_w_t_FromUTF8.xml"), ...
for wchar_t * in combination with
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
also in combination with
wxString mystring(buffor_ping_xml);
Then check out the look like, of the files in a browser .
To test you can go to your wxWidgets sample folder . Compile in the folder C:\wxWidgets\samples\docview\docview.cpp . Open with docview.exe a unicode file . How does it look.
Unicode download file
Unicode-related compilation settings
You should define wxUSE_UNICODE to 1 to compile your program in Unicode mode. This currently works for wxMSW, wxGTK, wxMac and wxX11. If you compile your program in ANSI mode you can still define wxUSE_WCHAR_T to get some limited support for wchar_t type.
Here is answear: Getting trash data in char* while using it as buffer in function.
Thanks everyone - expecially for patience.
I'm trying to use a COM object and i'm having problem with the parameter type VARIANT*. I can use the functions of the COM object just fine, except when they have a parameter of this type.
The doc generated by generateDocumentation is :
QVariantList params = ...
object->dynamicCall("GetRanges(int,int,int&, QVariant&)", params);
According to the doc provided with the COM object, the parameters should be of type LONG, LONG, LONG* and VARIANT*, and it is precised that the VARIANT* is a pointer to a VARIANT containing an array of BSTR.
I should normally be able to retrieve the third and fourth parameter (of type LONG* and VARIANT*), and their values are not used by the function.
Here is my code (a and b are int previously initialized):
QStringList sl;
QVariantList params;
int i = -1;
params << QVariant (a);
params << QVariant (b);
params << QVariant (i);
params << QVariant (sl);
comobject->dynamicCall("GetRanges(int,int,int&,QVariant&)",params);
sl = params[3].toStringList();
i = param[2].toInt();
Now with that code, all i get is an error QAxBase: Error calling IDispatch member GetRanges: Unknown error, which is not very helpful.
I tried to change some things and I managed to progress (sort of) by using this code :
QStringList sl;
QVariant v = qVariantFromValue(sl);
QVariantList params;
int i = -1;
params << QVariant (a);
params << QVariant (b);
params << QVariant (i);
params << qVariantFromValue((void*)&v);
comobject->dynamicCall("GetRanges(int,int,int&,QVariant&)",params);
sl = params[3].toStringList();
i = param[2].toInt();
It gets rid of the error, and the value of i is correct at the end, but sl is still empty. And I know it should not be, because I have a sample demo in C# that works correctly.
So if anyone has an idea on how to make it works...
Otherwise I looked around a bit and saw that it was also possible to query the interface ans use it directly, but I didn't understand much, and I'm not sure it will solve my problems.
I'm on a Windows7 64 bits platform, and I'm using msvc2012 as compiler. I'm using Qt 5.1.0 right now, but it didn't work in the 5.0.2 either.
I guess you really can't do it with dynamicCall.
I finally found how to do it. It was easier than I'd thought. With the installation of Qt comes a tool called dumpcpp. Its full path for me was C:\Qt\Qt5.1.0x86\5.1.0\msvc2012\bin\dumpcpp.exe (obviously depends on settings). You can just add the bin folder to your path to make it easier to use.
Then I went into my project folder and executed this command :
dumpcpp -nometaobject {00062FFF-0000-0000-C000-000000000046} (the CLSID is just for the example, not the one I used)
It creates a header file, you can include it in the file where you're trying to use the COM Object.
In this file in my case there was two classes (IClassMeasurement and ClassMeasurement) in a namespace (MeasurementLib). Again, the names are not the real ones.
In your initial project file, you can call the desired function like this :
MeasurementLib::ClassMeasurement test; //Do not use IClassMeasurement, you only get write access violations
QVariant rangesVar;
int p1 = 0;
int p2 = 0;
int p3 = 0;
test.getRanges(p1,p2,p3,ranges);
QStringList ranges = ranges.toStringList();
Hopes that it helps someone !
I am using the directory class to get this information but unable to assign this data to a data member of my own class. i am doing an oop project. Furthermore,I want to use the concept of Dynamism(containment).I have created two class, mydirectory and myfiles as under:
class files
{
string fname[25];
public:
files()
{
fname=NULL;
}
};
class directory
{ private:
directory *d;
string *dname[25]; //* to show there may be a subdirectory,there may be not.
files *ff[25]; // data member string *fname[25];
int numd,numf;
public:
directory()
{
numd=0;numf=0;
}
Now when if I want to use the statment:
Directory::GetDirectories("D:\\");
how can I assign the directory names to "dname" of directory class.
I dont want to include a third party software.
also i need help on the topic: how can a file (doc file/pdf/txt/pwt etc) can be opened from c++ code outside the console? I am very worried. please help me. thanks in advance.
I am new to c++ so please forgive if there are any errors in pointer handling, as I am doing this containment for the first time. I also need some reading stuff.
The simplest way to do it in C++ is using boost::filesystem.
As long as the path is a directory you can iterate over it using either a directory_iterator or a recursive_directory_iterator.
eg:
boost::filesystem::path dirname( "D:\\" );
std::vector<boost::filesystem::path> topLevel( directory_iterator(dirName),
directory_iterator() );
std::vector<boost::filesystem::path> wholeDrive(
recursive_directory_iterator(dirName), recursive_directory_iterator() );
As this is marked homework, we're not going to be helping you much by giving you the correct answer. But I will point you in the right direction.
You've indicated you're doing this under Visual C++. Well without using any third party libraries but just what's built in, you'll need to access the Win32 API.
FindFirstFile() & FindNextFile() are what you need.
You'll call FindFirstFile first off to obtain the directory handle.
The parameter is the D:\ that you're passing into your class.
Then call FindNextFile in a while loop.
e.g. The basic principle of using those API's is
HANDLE h = FindFirstFile("D:\\");
WIN32_FIND_DATA data;
while (FindNextFile(h, &data))
{
// Check if it's a directory or not
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
// Add to dname
}
}
Consider using std::vector for your dname instead of string*
because you're stuck with 25 entries. Using vector it'll grow for you.
As said CashCow, boost::filesystem
As a general rule, in C++ for such examples, you don't need any pointer. Here a some mistakes you should correct:
string fname[25];
This declares an array of 25 strings. You probably wanted a string of 25 chars ? Well, in std::string, you don't need to care about the length. std::string fname; is enough
std::string file_name;
file_name = "baz.txt";
fname=NULL;
If fname is a string, then it's not a pointer. So you can't assign NULL to it. A std::string is by default initialized as an empty string. You can leave the whole constructor out.
string *dname[25]
I suppose you wanted to have an array of string. Just use :
std::vector<std::string> dnames;
dnames.push_back("foo");
dnames.push_back("bar"); // dnames now contains {"foo","bar"}
And you'll have a dynamically resizable vector of strings.
See : no need of any pointer. No need for any new
Finally I completed the short project.To get the list of files and sub directories, I made use of .NET Framework namespace "System".It has got classes like "FileInfo" and "DirectoryInfo"(both belong to System::IO) which do the above required task.But here,all the string related stuff is of System::String , not of std::string.To convert System::String to std::string, I used the following code(I got this conversion's code from a forum and it worked fine without any error):
string Str2str(String ^a)
{
array<Byte> ^chars = System::Text::Encoding::ASCII->GetBytes(a);
pin_ptr<Byte> charsPointer = &(chars[0]);
char *nativeCharsPointer = reinterpret_cast<char *>(static_cast<unsigned char *>(charsPointer));
string native(nativeCharsPointer, chars->Length);
return native;
}
Here is a short code for getting list of sub directories from a drive(D: drive is going to be searched):
#include<iostream>
#using<mscorlib.dll>
using namespace strd;
using namespace System;
using namespace System::IO;
int main()
{int count=50;
string name[count];//to hold directories names
string b;
int s=0;
DirectoryInfo^ di = gcnew DirectoryInfo("d:\\");
if(di->Exists)
{array<DirectoryInfo^>^diArr = di->GetDirectories();
Collections::IEnumerator^ myEnum = diArr->GetEnumerator();
while ( myEnum->MoveNext() )
{DirectoryInfo^ dri = safe_cast<DirectoryInfo^>(myEnum->Current);
String ^a=(dri->Name->ToString());
int n=b.size();
b=Str2str(a); `// code given in the starting`
if (s<count)
{name[s]=b;
s++;}
}
This involves Managed C++ knowledge. Visit these:
.NET Programming Guide
C++: The Most Powerful Language for .NET Framework Programming
I compiled this on Visual Studio 2008. I will be very grateful if you appriciate my effort.Further suggestions are most welcomed.