C++ 从‘char*’到‘const unsigned char*’的无效转换
C++ invalid conversion from ‘char*’ to ‘const unsigned char*’
I'm writing my project in NodeJS, but I'm forced to use a C shared library. Because of this I have to use Node.js Addons. Calling the C++ code works perfectly, I was also able to load the custom library, and call two C functions successfully: one gives me the version number of the library, the other method generated a key based on the data provided form JS.
The problem that I'm having is related to the generated Key. I have to use in the encrypt
and decrypt
methods.
This is the variable that I'm using to store the key:
unsigned char generated_key[256];
This is the function that generates the key:
extern "C"
{
#ifdef WIN32
VE_EXPORT int CALLBACK generate_key
#else
int generate_key
#endif
(char *variable_msg, /*!< variable seed */
char *shared_seed, /*!< shared seed */
unsigned char *generated_key, /*!< generated key */
unsigned int key_size); /*!< key size */
}
This is a function that uses the key:
extern "C"
{
#ifdef WIN32
VE_EXPORT int CALLBACK encrypt
#else
int encrypt
#endif
(const unsigned char * const plain_data, /*!< plain data */
const unsigned int plain_data_len, /*!< number bytes to be encrypted */
unsigned char *encrypted_data, /*!< encrypted data */
const unsigned int encrypted_data_size, /*!< size encrypted_data array */
unsigned int *encrypted_data_len, /*!< number of bytes encrypted */
const unsigned char * const key /*!< symmetric encryption key */
);
}
When I try to compile the code I get:
gyp info it worked if it ends with ok
gyp info using node-gyp@3.4.0
gyp info using node@6.2.0 | linux | x64
gyp info spawn /usr/bin/python2
gyp info spawn args [ '/usr/local/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/usr/local/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/dgatti/.node-gyp/6.2.0/include/node/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/home/dgatti/.node-gyp/6.2.0',
gyp info spawn args '-Dnode_gyp_dir=/usr/local/lib/node_modules/node-gyp',
gyp info spawn args '-Dnode_lib_file=node.lib',
gyp info spawn args '-Dmodule_root_dir=/home/dgatti/sequr/sequr-experiments/CPP/Sequr',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.' ]
make: Entering directory `/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build'
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
CXX(target) Release/obj.target/vertx/main.o
../main.cpp: In function ‘void demo::VertxEncrypt(const v8::FunctionCallbackInfo<v8::Value>&)’:
../main.cpp:127:102: error: invalid conversion from ‘char*’ to ‘const unsigned char*’ [-fpermissive]
vertx_encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);
^
In file included from ../main.cpp:3:0:
../libvertx_encryption.h:79:7: error: initializing argument 1 of ‘int vertx_encrypt(const unsigned char*, unsigned int, unsigned char*, unsigned int, unsigned int*, const unsigned char*)’ [-fpermissive]
int vertx_encrypt
^
make: *** [Release/obj.target/vertx/main.o] Error 1
make: Leaving directory `/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/node-gyp/lib/build.js:276:23)
gyp ERR! stack at emitTwo (events.js:106:13)
gyp ERR! stack at ChildProcess.emit (events.js:191:7)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:204:12)
gyp ERR! System Linux 3.10.0-327.13.1.el7.x86_64
gyp ERR! command "/usr/local/bin/node" "/usr/local/bin/node-gyp" "rebuild"
gyp ERR! cwd /home/dgatti/sequr/sequr-experiments/CPP/Sequr
gyp ERR! node -v v6.2.0
gyp ERR! node-gyp -v v3.4.0
gyp ERR! not ok
This is how I call the function, right now I'm just passing the variable as is, but I tried many different way of converting, casting and changing.
encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);
I wrote an example in C and everything works fine, but when I try to use this C functions in C++, things brakes. I have experience in C but defiantly not in C++. I looked for days to find a solution but uncle Google and buddy Stack weren't able to com up with a solution.
What I'm looking for
- a keyword that could help me in my search for an answer,
- or the solution to my problem.
Tech spec
- gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
Complete code
This is the complete code in C++ that I'm calling from NodeJS to access C functions:
#include <node.h>
#include <iostream>
#include "lib_encryption.h"
using namespace std;
namespace demo {
using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;
unsigned char generated_key[256];
unsigned int key_size = 32;
unsigned int encLength;
unsigned char encMessage[256] = {0};
//
// This is the implementation of the "add" method
// Input arguments are passed using the
// const FunctionCallbackInfo<Value>& args struct
//
void GenerateKey(const FunctionCallbackInfo<Value>& args)
{
v8::String::Utf8Value param1(args[0]->ToString());
std::string strMessage = std::string(*param1);
v8::String::Utf8Value param2(args[1]->ToString());
std::string strSecret = std::string(*param2);
char cMessage[4];
strcpy(cMessage, strMessage.c_str());
char cSecret[11];
strcpy(cSecret, strSecret.c_str());
//
// Creating the key
//
_generate_key(cMessage, cSecret, generated_key, key_size);
//
// 1. Create isolation storage
//
Isolate* isolate = args.GetIsolate();
//
// 2. Save the value in to a isolate storage
//
Local<Value> str = String::NewFromUtf8(isolate, "Key done");
//
// 3. Set the return value (using the passed in
// FunctionCallbackInfo<Value>&)
//
args.GetReturnValue().Set(str);
}
void Encrypt(const FunctionCallbackInfo<Value>& args)
{
Isolate* isolate = args.GetIsolate();
v8::String::Utf8Value param1(args[0]->ToString());
std::string payload = std::string(*param1);
char cPayload[4];
strcpy(cPayload, payload.c_str());
for (int i=0; i<256; i++)
{
printf("%.2X ", generated_key[i]);
}
printf("\n");
encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);
//
// 1. Create isolation storage
//
//
// 2. Save the value in to a isolate storage
//
Local<Value> str = String::NewFromUtf8(isolate, "Encrypt");
//
// 3. Set the return value (using the passed in
// FunctionCallbackInfo<Value>&)
//
args.GetReturnValue().Set(str);
}
//
// * Initialize the object and expose the functions that need exposure.
//
void Init(Local<Object> exports)
{
NODE_SET_METHOD(exports, "GenerateKey", GenerateKey);
NODE_SET_METHOD(exports, "Encrypt", Encrypt);
}
//
// There is no semi-colon after NODE_MODULE as it's not a function
//
NODE_MODULE(, Init)
}
我想我没明白代码的哪一部分有问题。但是我认为您正在尝试从两种不同类型的 char* 转换为 const unsigned char* 。尝试将 char* 类型更改为 unsigned char* 或在代码中的所有位置使用 unsigned char*。
这是一个答案,可能会对您有所帮助 Plain char、signed char 和 unsigned char 是三种不同的类型。
Conversion from char* to signed char*
默认的 char
类型具有实现定义的符号性,可以是有符号的也可以是无符号的,具体取决于编译器。因此,它不应该被用来存储字符串以外的任何东西。永远不要用它来存储其他形式的数据。它不一定与 unsigned char
.
兼容
它无法编译的原因可能是因为 C 和 C++ 编译器之间的符号 if char
不同,但也可能是因为 C++ 具有比 C 更严格、更好的类型安全系统。虽然C 编译器更宽松,可能会让代码在不引发诊断消息的情况下通过,即使在 C 和 C++ 中混合这些类型总是不好的做法。
只需更改为 unsigned char
或最好是 uint8_t
,问题就会消失。
其他答案只提背景,不提具体问题,或者对generated_key
提出质疑,但那个没问题。 [edit] 我现在看到了 molbdnilo 的评论;我以为有人提到过,但我好像找不到! [/edit] 所以这是真正的原因:
对象 cPayload
是一个 char[4]
。与任何数组一样,它的名称在多种情况下(包括将其作为函数参数传递时)隐式转换(通常通俗地表述为 'decays')为 char *
。您将它传递给一个函数 encrypt()
,该函数在该位置需要一个 unsigned char *
。但是 char *
和 unsigned char *
是两种截然不同的类型。因此错误。
回到后台,因为值得指定。 char
必须具有与 signed char
或 unsigned char
相同的值范围,可以是 static_cast
并可能被截断,并且具有相同的别名权限 - 等等 - 但是,在无论如何,它被认为是一个独特的类型。您可以通过检查 3 种类型的 typeid
结果来验证这一点而不会出现任何编译错误。
I'm writing my project in NodeJS, but I'm forced to use a C shared library. Because of this I have to use Node.js Addons. Calling the C++ code works perfectly, I was also able to load the custom library, and call two C functions successfully: one gives me the version number of the library, the other method generated a key based on the data provided form JS.
The problem that I'm having is related to the generated Key. I have to use in the encrypt
and decrypt
methods.
This is the variable that I'm using to store the key:
unsigned char generated_key[256];
This is the function that generates the key:
extern "C"
{
#ifdef WIN32
VE_EXPORT int CALLBACK generate_key
#else
int generate_key
#endif
(char *variable_msg, /*!< variable seed */
char *shared_seed, /*!< shared seed */
unsigned char *generated_key, /*!< generated key */
unsigned int key_size); /*!< key size */
}
This is a function that uses the key:
extern "C"
{
#ifdef WIN32
VE_EXPORT int CALLBACK encrypt
#else
int encrypt
#endif
(const unsigned char * const plain_data, /*!< plain data */
const unsigned int plain_data_len, /*!< number bytes to be encrypted */
unsigned char *encrypted_data, /*!< encrypted data */
const unsigned int encrypted_data_size, /*!< size encrypted_data array */
unsigned int *encrypted_data_len, /*!< number of bytes encrypted */
const unsigned char * const key /*!< symmetric encryption key */
);
}
When I try to compile the code I get:
gyp info it worked if it ends with ok
gyp info using node-gyp@3.4.0
gyp info using node@6.2.0 | linux | x64
gyp info spawn /usr/bin/python2
gyp info spawn args [ '/usr/local/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/usr/local/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/dgatti/.node-gyp/6.2.0/include/node/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/home/dgatti/.node-gyp/6.2.0',
gyp info spawn args '-Dnode_gyp_dir=/usr/local/lib/node_modules/node-gyp',
gyp info spawn args '-Dnode_lib_file=node.lib',
gyp info spawn args '-Dmodule_root_dir=/home/dgatti/sequr/sequr-experiments/CPP/Sequr',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.' ]
make: Entering directory `/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build'
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
CXX(target) Release/obj.target/vertx/main.o
../main.cpp: In function ‘void demo::VertxEncrypt(const v8::FunctionCallbackInfo<v8::Value>&)’:
../main.cpp:127:102: error: invalid conversion from ‘char*’ to ‘const unsigned char*’ [-fpermissive]
vertx_encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);
^
In file included from ../main.cpp:3:0:
../libvertx_encryption.h:79:7: error: initializing argument 1 of ‘int vertx_encrypt(const unsigned char*, unsigned int, unsigned char*, unsigned int, unsigned int*, const unsigned char*)’ [-fpermissive]
int vertx_encrypt
^
make: *** [Release/obj.target/vertx/main.o] Error 1
make: Leaving directory `/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/node-gyp/lib/build.js:276:23)
gyp ERR! stack at emitTwo (events.js:106:13)
gyp ERR! stack at ChildProcess.emit (events.js:191:7)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:204:12)
gyp ERR! System Linux 3.10.0-327.13.1.el7.x86_64
gyp ERR! command "/usr/local/bin/node" "/usr/local/bin/node-gyp" "rebuild"
gyp ERR! cwd /home/dgatti/sequr/sequr-experiments/CPP/Sequr
gyp ERR! node -v v6.2.0
gyp ERR! node-gyp -v v3.4.0
gyp ERR! not ok
This is how I call the function, right now I'm just passing the variable as is, but I tried many different way of converting, casting and changing.
encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);
I wrote an example in C and everything works fine, but when I try to use this C functions in C++, things brakes. I have experience in C but defiantly not in C++. I looked for days to find a solution but uncle Google and buddy Stack weren't able to com up with a solution.
What I'm looking for
- a keyword that could help me in my search for an answer,
- or the solution to my problem.
Tech spec
- gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
Complete code
This is the complete code in C++ that I'm calling from NodeJS to access C functions:
#include <node.h>
#include <iostream>
#include "lib_encryption.h"
using namespace std;
namespace demo {
using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;
unsigned char generated_key[256];
unsigned int key_size = 32;
unsigned int encLength;
unsigned char encMessage[256] = {0};
//
// This is the implementation of the "add" method
// Input arguments are passed using the
// const FunctionCallbackInfo<Value>& args struct
//
void GenerateKey(const FunctionCallbackInfo<Value>& args)
{
v8::String::Utf8Value param1(args[0]->ToString());
std::string strMessage = std::string(*param1);
v8::String::Utf8Value param2(args[1]->ToString());
std::string strSecret = std::string(*param2);
char cMessage[4];
strcpy(cMessage, strMessage.c_str());
char cSecret[11];
strcpy(cSecret, strSecret.c_str());
//
// Creating the key
//
_generate_key(cMessage, cSecret, generated_key, key_size);
//
// 1. Create isolation storage
//
Isolate* isolate = args.GetIsolate();
//
// 2. Save the value in to a isolate storage
//
Local<Value> str = String::NewFromUtf8(isolate, "Key done");
//
// 3. Set the return value (using the passed in
// FunctionCallbackInfo<Value>&)
//
args.GetReturnValue().Set(str);
}
void Encrypt(const FunctionCallbackInfo<Value>& args)
{
Isolate* isolate = args.GetIsolate();
v8::String::Utf8Value param1(args[0]->ToString());
std::string payload = std::string(*param1);
char cPayload[4];
strcpy(cPayload, payload.c_str());
for (int i=0; i<256; i++)
{
printf("%.2X ", generated_key[i]);
}
printf("\n");
encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);
//
// 1. Create isolation storage
//
//
// 2. Save the value in to a isolate storage
//
Local<Value> str = String::NewFromUtf8(isolate, "Encrypt");
//
// 3. Set the return value (using the passed in
// FunctionCallbackInfo<Value>&)
//
args.GetReturnValue().Set(str);
}
//
// * Initialize the object and expose the functions that need exposure.
//
void Init(Local<Object> exports)
{
NODE_SET_METHOD(exports, "GenerateKey", GenerateKey);
NODE_SET_METHOD(exports, "Encrypt", Encrypt);
}
//
// There is no semi-colon after NODE_MODULE as it's not a function
//
NODE_MODULE(, Init)
}
我想我没明白代码的哪一部分有问题。但是我认为您正在尝试从两种不同类型的 char* 转换为 const unsigned char* 。尝试将 char* 类型更改为 unsigned char* 或在代码中的所有位置使用 unsigned char*。 这是一个答案,可能会对您有所帮助 Plain char、signed char 和 unsigned char 是三种不同的类型。
Conversion from char* to signed char*
默认的 char
类型具有实现定义的符号性,可以是有符号的也可以是无符号的,具体取决于编译器。因此,它不应该被用来存储字符串以外的任何东西。永远不要用它来存储其他形式的数据。它不一定与 unsigned char
.
它无法编译的原因可能是因为 C 和 C++ 编译器之间的符号 if char
不同,但也可能是因为 C++ 具有比 C 更严格、更好的类型安全系统。虽然C 编译器更宽松,可能会让代码在不引发诊断消息的情况下通过,即使在 C 和 C++ 中混合这些类型总是不好的做法。
只需更改为 unsigned char
或最好是 uint8_t
,问题就会消失。
其他答案只提背景,不提具体问题,或者对generated_key
提出质疑,但那个没问题。 [edit] 我现在看到了 molbdnilo 的评论;我以为有人提到过,但我好像找不到! [/edit] 所以这是真正的原因:
对象 cPayload
是一个 char[4]
。与任何数组一样,它的名称在多种情况下(包括将其作为函数参数传递时)隐式转换(通常通俗地表述为 'decays')为 char *
。您将它传递给一个函数 encrypt()
,该函数在该位置需要一个 unsigned char *
。但是 char *
和 unsigned char *
是两种截然不同的类型。因此错误。
回到后台,因为值得指定。 char
必须具有与 signed char
或 unsigned char
相同的值范围,可以是 static_cast
并可能被截断,并且具有相同的别名权限 - 等等 - 但是,在无论如何,它被认为是一个独特的类型。您可以通过检查 3 种类型的 typeid
结果来验证这一点而不会出现任何编译错误。