|
Right click the project, and choose "Add Class", then choose a C++ class.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
problem piece of code - if(Function(parm1, parm2, parm3)==0){
error - cannot convert parameter 3 from 'char [1024]' to 'wchar_t *'
parm3 is an array -
//char parm3[Buffsize1024]; //was before
wchar_t parm3[Buffsize1024]; // I changed to make the application unicode enabled
Function is expecting wchar_t but its getting char[1024] from some where.
I also changed the function signature to accept wchar_t type in header file.
objective is to make the whole code UNICODE enabled. I have added all the tchar.h, wchar.h fiels
param 3 has been defined (modified) as wchar_t in all the connected files too.
I also tried to cast the string and pass the casted string.
CString s(parm3)
LPCTSTR p = s;
no change in the error.
I cant debug yet. Pls help how can I get rid of this error.
|
|
|
|
|
Something in your code has not been converted correctly. Go to the source code and look carefully at the line where the error occurs. Also please use <pre> tags around your code so it is more readable, like:
wchar_t parm3[Buffsize1024];
if(Function(parm1, parm2, parm3)==0){
|
|
|
|
|
Have you tried
Project properties->Configuration properties->Char set->Unicode
|
|
|
|
|
when the menu so long, for example, the favorites of IE. how to let menu auto show next item when mouse on the bottom arrow of the menu
|
|
|
|
|
|
Visual Studio 2008, C++
Class C_AR2_Messages process telemetry messages. The configuration is quite complex so class C_Configuration_Manager reads a configuration file and loads the data into the structures/variable of C_AR2_Messages.
Please note that my work is on a classified computer and I cannot cut and paste from there to here. I probably put in a few typos. Please note them, but take that into consideration.
The message class contains:
The messages class contains
Class C_AR2_Messages
{ …
WCHAR m_common_parameter_names _NAMES[ COMMON_ARRAY_SIZE ][ MAX_PARAMETER_NAME_LENGTH ];
All the below fail compile but to me, they match the examples I have found in my searches. Two of them claim that the open brace is a syntax error.
WCHAR m_test[ ] [ ] = { {L"one"}, { L"two" }, { L"three" } };
WCHAR m_test_2[ 3 ] [8 ] = { {L"one"}, { L"two" }, { L"three" } };
Wstring m_test_3[ ] = { L"one", L"two", L"three" };
Meanwhile back in class C_Configuration_Manager.h, there is a method used to hand that class the pointer giving it access. It looks like:
Class C_Configuration_Manager
{ …
VOID Set_Common_Names_Pointer( WCHAR *new_pointer[COMMON_ARRAY_SIZE ][ MAX_PARAMETER_NAME_LENGTH ] );
WCHAR mp_common_parameter_names[COMMON_ARRAY_SIZE ][ MAX_PARAMETER_NAME_LENGTH ];
and C_Configuration_Manager.cpp contains:
VOID Set_Common_Names_Pointer( WCHAR *new_pointer[COMMON_ARRAY_SIZE ][ MAX_PARAMETER_NAME_LENGTH ] )
{ mp_common_parameter_names = new_pointer; }
The compiler says:
Quote: Error C2440: ‘=’ cannot convert from WCHAR *[] [34] to ‘WCHAR *[18][34]
To my knowledge, both are declared as [18][34]
So having failed on two fronts, I open a third front in this war by editing C_AR2_Messages with
Class C_AR2_Messages
{ …
Friend class C_Configuration_Manager;
Then back in C_Configuration_Manager.cpp added this to access those member variables in C_AR2_Messages
Wstring test1 = common_parameter_names[ 0 ] [ 0 ];
Wstring test1 = C_Configuration_Manager ::common_parameter_names[ 0 ] [ 0 ];
So I have failed on all three attempts to gain access to that data in the configuration class. Will someone provide the knowledge I need to accomplish this task?
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
modified 7-Jul-14 19:57pm.
|
|
|
|
|
You are getting confused between character Variables (WCHAR) and character arrays (WCHAR[][]) . Your array of names should be declared as an array of pointers and initialised with strings like:
WCHAR* some_names[] = { { "name1" }, { "name2" }, ... };
PWSTR some_names[] = { { "name1" }, { "name2" }, ... };
The wstring type is part of the STL library and is best avoided unless you are familiar with the use of all the features of that library.
|
|
|
|
|
The array of character strings versus array of pointer was a good point. I will focus my question a bit tighter.
From C_AR2_Messages.h
WCHAR m_test_1_[COMMON_ARRAY_SIZE][MAX_PARAMETER_NAME_LENGTH];
COMMON_ARRAY_SIZE is const unsigned int = 18 and MAX_PARAMETER_NAME_LENGTH is same = 34, this is 18 WCHAR strings, each 34 characters long. I verified this by writing the following code in the constructor and stepping though with the debugger.
wcscpy_s( m_test_1[0], MAX_PARAMETER_NAME_LENGTH, L"[0] 1234"
wcscpy_s( m_test_1[1], MAX_PARAMETER_NAME_LENGTH, L"[1] 1234"
wcscpy_s( m_test_1[2], MAX_PARAMETER_NAME_LENGTH, L"[2] 1234"
wstring test_5 = m_test_1[0];
wstring test_6 = m_test_1[1];
wstring test_7 = m_test_1[2];
Actually, the strings “1234” were continued out to about 25 characters to ensure the length was greater than 18.
The wstrings were used as a very convenient tool to capture the text from the strings and see what was there. I am confident that in C_AR2_Messages I have a good declaration for m_test_1 as an array of 18 character strings, each 34 characters in length.
The Goal
In C_Configuration_Manager the code reads a text file and initializes a bunch of parameters. It needs to read and right to those strings contained by m_test_1. My plan is to hand it the address of m_test_1. I am having difficulties with that. Here is what I have come up with.
In C_Configuration_Manager.h
WCHAR *mp_common_parameter_names [COMMON_ARRAY_SIZE][MAX_PARAMETER_NAME_LENGTH];
That is to be a pointer to the array of strings. Then in C_Configuration_Manager dot CPP is the definition of the method to set the pointer:
Void C_Configuration_Manager::Set_common_names_Pointer(
WCHAR *new_pointer[ COMMON_ARRAY_SIZE][MAX_PARAMETER_NAME_LENGTH] )
{ mp_common_parameter_names = new_pointer; }
That did not work so well. The compiler says:
Quote: 1>e:\visual|studio\ar2_message_app_v11.1\ar2_message_app\c_configuration_manager.cpp(120)
: error C2440: ‘=’ : cannot convert from ‘WCHAR 8[][34] TO ‘wchar *[18][34]’
1> There are no conversions to array types, although there are conversions to references or pointers to arrays
Note that the first [ ] in the error message is empty. None of the declarations have an empty [ ].
With the thought of arrays of strings versus arrays of pointers I tried changing the declarations in C_Configuration_Manager to:
WCHAR * (mp_common_parameter_names [COMMON_ARRAY_SIZE][MAX_PARAMETER_NAME_LENGTH] );
Note the added parens and the attempt to set order of operation and get a pointer to an array of strings. The error message was exactly the same.
So, …, how do I declare a pointer to an array of strings in the configuration_manager?
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
|
|
|
|
|
I think rather you are widening it. Your code will be far more flexible if you use dynamic arrays, rather than fixed size, and even use vectors and strings from the STL. Apart from anything else you will avoid all these annoying compilation issues.
|
|
|
|
|
Hello Richard,
Re: Your code will be far more flexible if you use dynamic arrays, rather than fixed size ....
That will not work for this project. It is a telemetry project and the data arrives fast and furious. We are collecting data from very expensive missiles that travel very fast.
I tried using an std::map. It made writing the code much easier, but it was definitely far to slow. Too much overhead in the template libraries. When I was testing the std::map, I stepped into the code to fetch an integer. After about a hundred function calls to get that integer I knew that was the problem. The buffers from the sender were overflowing constantly. As soon as I deleted the map and went to a fixed size array, the cpu time of this application went down to about 1%. I started four copies for four different streams on one machine and had no problem.
The wstring is used when I am reading from a file as the tokenizer needs it. The data is saved in WCHAR (wchar_t) and for real time is used in that format.
So, for a re-cap. I want a declaration of N number of WCHAR strings as in:
WCHAR names[ STRING_COUNT ][ SIZE_OF_STRING ];
I have that working.
Then I want a procedure to take the address of that array of strings and hand it to a local pointer as in:
void Set_Local_Pointer( WCHAR * new_pointer[ STRING_COUNT][SIZE_OF_STRING ] )
{ mp_local_pointer = new_pointer; }
What is the right way to declare mp_local_pointer?
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
|
|
|
|
|
The problem you have is that you cannot declare an array and then 'set it' to point to something else, it is not modifiable. The only way to do it (but I would not recommend it) is to use simple pointers, and let the code in your class figure out the length of each string in the array; in your case this is the fixed value SIZE_OF_STRING . So your code would need to be implemented like:
WCHAR* names;
void Set_Local_Pointer(WCHAR* new_pointer)
{
mp_local_pointer = new_pointer;
}
WCHAR names[ STRING_COUNT ][ SIZE_OF_STRING ];
wcscpy_s(names[0], L"StringZero");
wcscpy_s(names[1], L"StringOne");
wcscpy_s(names[2], L"StringTwo");
Set_Local_Pointer(names[0])
A better way would be to let the class object manage all the data by sending it the strings as a list, or with an index telling it which element to modify. something like:
BlahBlah class
{
WCHAR mpNames[STRING_COUNT][SIZE_OF_STRING];
void Set_Local_Pointer(WCHAR new_pointer)
{
memcpy(mp_local_pointer, new_pointer, STRING_COUNT * SIZE_OF_STRING);
}
void Set_Local_Pointer(WCHAR pLabel, int index)
{
memcpy(mp_local_pointer[index], pLabel, SIZE_OF_STRING);
}
|
|
|
|
|
The configuration class is to make changes to several data items needed by the AR2_Messages class. I don't think memcpy will provide the results needed. If I can do memcpy, then when can I not just set a pointer.
I have been nibbling around the edges but cannot quite get a full chomp on this cookie.
I have created a Console App project just to test the concept. While doing that I discovered that a Console App gets indigestion on WCHAR so I changed to wchar_t. Here is my best effort so far.
#include "stdafx.h"
const unsigned int COMMON_ARRAY_SIZE = 10;
const unsigned int MAX_NAME_SIZE = 34;
void Set_Pointer( wchar_t new_pointer[ COMMON_ARRAY_SIZE ][ MAX_NAME_SIZE ])
{
wchar_t local_pointer[ COMMON_ARRAY_SIZE ][ MAX_NAME_SIZE ];
wchar_t one[ MAX_NAME_SIZE ];
wchar_t two[ MAX_NAME_SIZE ];
local_pointer = new_pointer;
wcscpy_s( one, MAX_NAME_SIZE, local_pointer[0] );
wcscpy_s( two, MAX_NAME_SIZE, new_pointer[1] );
};
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t names[ COMMON_ARRAY_SIZE ][ MAX_NAME_SIZE ];
wcscpy_s( names[ 0 ], MAX_NAME_SIZE, L"[0] 123" );
wcscpy_s( names[ 1 ], MAX_NAME_SIZE, L"[1] 123" );
wcscpy_s( names[ 2 ], MAX_NAME_SIZE, L"[2] 123" );
wcscpy_s( names[ 3 ], MAX_NAME_SIZE, L"[3] 123" );
Set_Pointer( names );
return 0; }
The line marked as line 12 will not compile producing the following error:
Quote: Error 1 error C2440: '=' : cannot convert from 'wchar_t [][34]' to 'wchar_t [10][34]'
I note that there is NOT any variable/array declared as [][34]. Trying to convert from [][34] appears to be a misleading error message.
Not the line commented as line 15. When line 12 is commented out the code will copy to the local string using the argument pointer directly. So why does is refuse to set the local pointer, declared with exactly the same syntax? More important, how can I change to code to allow that pointer set?
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
|
|
|
|
|
I explained in my previous message why line 12 will not compile, local_pointer is not a pointer it is an array. You cannot set an array equal to another array, you can only copy the content from one to another. Your use of the term pointer in some of your variable names is helping to confuse the issue, as they are not pointers.
So your code should be:
wchar_t local_array[ COMMON_ARRAY_SIZE ][ MAX_NAME_SIZE ];
wcscpy_s(local_array[0], MAX_NAME_SIZE, new_pointer[0]);
memcpy(local_array, new_pointer, COMMON_ARRAY_SIZE * MAX_NAME_SIZE);
If you want to use pointers then you must remember that all you are doing is keeping a pointer to the original data array in memory like:
wchar_t* local_pointer;
local_pointer = new_pointer;
So you must now ensure that that original data is not overwritten.
|
|
|
|
|
Well that was rather stupid on my part. This is what I want to accomplish in the procedure:
void Set_Pointer( wchar_t *new_pointer)
{
wchar_t *local_pointer;
wchar_t one[ MAX_NAME_SIZE ];
wchar_t two[ MAX_NAME_SIZE ];
wchar_t three[ MAX_NAME_SIZE ];
wchar_t four[ MAX_NAME_SIZE ];
local_pointer = new_pointer;
wcscpy_s( one, MAX_NAME_SIZE, local_pointer );
wcscpy_s( two, MAX_NAME_SIZE, local_pointer[1] );
wcscpy_s( three, MAX_NAME_SIZE, local_pointer[2] );
wcscpy_s( four, MAX_NAME_SIZE, local_pointer[3] );
};
The three lines that cannot convert have the error:
Quote: Error 1 error C2664: 'errno_t wcscpy_s(wchar_t *,rsize_t,const wchar_t *)' : cannot convert parameter 3 from 'wchar_t' to 'const wchar_t *'
The caller is to pass a pointer to an array defined in the manner
wchar_t some_array[ x ] [ y ];
where x and y are named constants.
What needs to be done?
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
modified 4-Jul-14 7:23am.
|
|
|
|
|
local_pointer[1] is the second character in the array pointed to by local_pointer . I'm sorry to have to say this, but you really need to spend some time studying the differences between, and the uses of, pointers and arrays in C++.
|
|
|
|
|
|
Hello Richard,
I know I am trying your patience and I am quite grateful for your help.
I went back to your example and changed my code to match. That version works partially, but it does not use the pointer in the procedure to access the data. Look first and the call to the procedure in main and the two critical lines of code:
wchar_t names[ COMMON_ARRAY_SIZE ][ MAX_NAME_SIZE ];
Set_Pointer( &names[0][0] );
That is the only way I can get a good compile. Given that, here are the critical line from the procedure:
void Set_Pointer( wchar_t *new_pointer)
{
wchar_t *mp_local_pointer;
mp_local_pointer = new_pointer;
wcscpy_s( one, MAX_NAME_SIZE, mp_local_pointer );
wcscpy_s( two, MAX_NAME_SIZE, mp_local_pointer[1] );
...}
The first copy with source string mp_local_pointer produces the desired results. But there are more strings there to be accessed. The second line with
mp_local_pointer[1] will not compile. When the array dimensions are added in, I get back to where I started.
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
|
|
|
|
|
bkelly13 wrote: I get back to where I started. Hence the final comment in my previous answer.
The issue is that you are trying to copy data from a multi-dimensional array using a single dimension pointer; and given the structure of your original array you have no other choice. If you used the memcpy option which I suggested and just copy the entire array to a new array inside the class then you have your data correctly saved.
If you want to do it the hard way then you can do this:
wchar_t savedItems[COMMON_ARRAY_SIZE][MAX_NAME_SIZE];
wchar_t* localPointer;
localPointer = new_pointer;
for (int i = 0; i < COMMON_ARRAY_SIZE; ++i)
{
wcscpy_s(savedItems[i], MAX_NAME_SIZE, localPointer);
localPointer += MAX_NAME_SIZE; }
If you want to do it with individually named items then just copy them in order, remembering to add MAX_NAME_SIZE to localPointer after each copy.
|
|
|
|
|
Hello Richard,
Re:
The issue is that you are trying to copy data from a multi-dimensional array using a single dimension pointer; and given the structure of your original array you have no other choice.
It seems to me that what you are not explicitly saying is that we CAN NOT create a pointer to a two dimension array and pass that to another procedure. Is that correct?
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
|
|
|
|
|
No, that's not what I'm saying. A pointer to an array of any size and number of dimensions, points to the elementary item of the array that it references. In your case, that item is a wchar_t so the pointer is defined as pointing to a simple array of characters; that is what gives rise to the problems you are having. If you defined your basic item as a structure rather than an array of characters, then you could make things easier. Something like:
struct dataArray
{
wchar_t item[ MAX_NAME_SIZE ];
} names[COMMON_ARRAY_SIZE];
Set_Pointer(names);
void Set_Pointer(dataArray* new_pointer)
{
dataArray* mp_local_pointer;
mp_local_pointer = new_pointer;
wcscpy_s(one, MAX_NAME_SIZE, dataArray[0].item); wcscpy_s(two, MAX_NAME_SIZE, dataArray[1].item); ...
}
By using a struct rather than a simple array the compiler knows the size of each structure (from its definition) and hence, how to access each individual item when using a pointer to the array of structures.
|
|
|
|
|
Here is my solution that demonstrates passing the pointer and gaining access to the array of strings:
#include "stdafx.h"
const unsigned int COMMON_ARRAY_SIZE = 10;
const unsigned int MAX_NAME_SIZE = 34;
struct st2_names
{
wchar_t names[ COMMON_ARRAY_SIZE ] [ MAX_NAME_SIZE ];
};
void Set_Pointer_2( st2_names *new_pointer );
int _tmain(int argc, _TCHAR* argv[])
{
st2_names names_2;
wcscpy_s( names_2.names[0] , MAX_NAME_SIZE, L"PITCH" );
wcscpy_s( names_2.names[1] , MAX_NAME_SIZE, L"ROLL" );
wcscpy_s( names_2.names[2] , MAX_NAME_SIZE, L"YAW" );
wcscpy_s( names_2.names[3] , MAX_NAME_SIZE, L"VELOCITY" );
Set_Pointer_2( &names_2 );
return 0;
}
void Set_Pointer_2( st2_names *new_pointer )
{
st2_names *mp_names_2;
mp_names_2 = new_pointer;
wchar_t t1[MAX_NAME_SIZE];
wchar_t t2[MAX_NAME_SIZE];
wchar_t t3[MAX_NAME_SIZE];
wchar_t t4[MAX_NAME_SIZE];
wcscpy_s( t1, MAX_NAME_SIZE, mp_names_2->names[0] );
wcscpy_s( t2, MAX_NAME_SIZE, mp_names_2->names[1] );
wcscpy_s( t3, MAX_NAME_SIZE, mp_names_2->names[2] );
wcscpy_s( t4, MAX_NAME_SIZE, mp_names_2->names[3] );
}
It is a but ugly, but does work. EDIT, I did simplify.
It does seem to me that you are saying: No, there is no way to create a simple multi-dimension array such as:
wchar_t names[ x ] [ y ];
and pass a pointer to a procedure, then use that pointer to access all the elements of the array.
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
modified 4-Jul-14 15:30pm.
|
|
|
|
|
bkelly13 wrote: It does seem to me that you are saying No, I have never said that. I have explained a number of different ways how you can use such a pointer, even though it may seem non-intuitive.
And I still think that you are making life more difficult for yourself by not using a simple memcpy to copy the entire structure, since that is all you want in the end result.
|
|
|
|
|
taking things a bit out of order.
The core code, C_AR2_Messages, hands the pointer over to C_Configuration_Manager. That code reads a text file and changes the names adding a prefix to them. When C_AR2_Messages resumes control, it queries another application (a vendor app) to acquire more information about the parameter. So memcopy to C_Configuration Manager does not work out.
Yes, you have given me hints and clues. But I cannot figure out how to change the example code to compile such that the pointer can be saved and used to read and write the array of strings.
I apologize for being rather slow, but do appreciate the time you spend trying to help me.
Thank you for your time
If you work with telemetry, please check this bulletin board: www.irigbb.com
|
|
|
|
|
bkelly13 wrote: I apologize for being rather slow We all had to learn from the beginning to get where we are now. I couldn't begin to understand the basics of telemetry.
However, from your description above I have put together the following. It's making a few (possibly incorrect) assumptions about where the structure should be declared and whether it is the only one you use, but I hope it may give you something to work on.
struct st2_names
{
wchar_t names[ COMMON_ARRAY_SIZE ] [ MAX_NAME_SIZE ];
};
int C_Configuration_Manager(st2_names *new_pointer)
{
wcscpy_s(new_pointer->names[0], MAX_NAME_SIZE, L"PITCH" );
wcscpy_s(new_pointer->names[1], MAX_NAME_SIZE, L"ROLL" );
wcscpy_s(new_pointer->names[2], MAX_NAME_SIZE, L"YAW" );
wcscpy_s(new_pointer->names[3], MAX_NAME_SIZE, L"VELOCITY" );
return 0;
}
int C_AR2_Messages(st2_names *dataPointer)
{
C_Configuration_Manager(dataPointer);
CallOtherFunction(dataPointer);
return 0;
}
int wmain(int argc, wchar_t* argv[])
{
st2_names dataNames;
memset(&dataNames, 0, sizeof dataNames);
C_AR2_Messages(&dataNames);
return 0;
}
|
|
|
|
|