C++ problème de conversion de type string/char*

Addon C++ pour nodejs v12.x

a marqué ce sujet comme résolu.

Bonjour,

Je suis actuellement en train de faire un addon C++ pour nodejs v12.x.

Quand je fais : args.GetReturnValue().Set((int) FindWindowA(NULL, "Calculatrice")); tout fonctionne bien mais quand j’essaye d’implémenter une variable à la place de "Calculatrice" j’obtiens:

error C2665: 'FindWindowA' : aucune des 2 surcharges n’a pu convertir tous les types d’arguments.

Je n’arrive donc pas à convertir ma variable string au bon format (j’imagine c’est que j’ai un char* et que j’essaye de transmettre un string), j’ai pu parcourir la doc:

Mon code :

#include <node.h>
#include <windows.h>

using v8::Context;
using v8::FunctionCallbackInfo;
using v8::Int32;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

typedef struct tagRECT RECT;

static void FindWindow(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  //Local<Context> context = isolate->GetCurrentContext();

  //Local<String> appName = args[0]->ToString(context).ToLocalChecked();

  args.GetReturnValue().Set((int) FindWindowA(NULL, "calculatrice"));
}

extern "C" NODE_MODULE_EXPORT void
NODE_MODULE_INITIALIZER(Local<Object> exports,
                        Local<Value> module,
                        Local<Context> context) {
  NODE_SET_METHOD(exports, "FindWindow", FindWindow);
}
config de mon build

binding.gyp:

{
  "targets": [
    {
      "target_name": "FindWindow",
      "sources": [ "src/FindWindow.cc" ]
    }
  ]
}

Pour build je fais : node-gyp configure build

Bon vol,

A.

En gros quand tu appelles FindWindowA(), le type des arguments est LPCSTR. Et LPCSTR est défini comme étant équivalent à un const char* (en fait un typedef (définition d’un type custom) se fait comme ça : typedef <n_importe quoi qui défini ton type> <nom_du_nouveau_type>). donc en argument de FindWindowA tu dois lui passer des arguments de type const char*. (et en fait quand tu écris FindWindowA(NULL, "calculatrice"), "calculatrice" est automatiquement converti en const char* (puisque tu ne peux pas modifier une string litérale). Donc :

const char* var = "calc";
// ou LPCSTR var = "calc";
FindWindowA(NULL, var);

@Vanadiae: ??? Non. Si une fonction prend un const char* ça veux simplement dire qu’elle ne modifiera pas la chaîne. Tu peux bien-sûr lui passer un char*. Le type d’une chaîne littérale est tableau sur char, il n’est pas constant mais sa modification est un comportement indéterminé, ce n’est pas une const char*.

Si tu as un string mais que tu as besoin d’une chaîne de caractères 0-ended style C. Alors tu peux utiliser la méthode c_str de string.

+1 -0
const char* var = "calc";
// ou LPCSTR var = "calc";
FindWindowA(NULL, var);

Vanadiae

Mon problème est surtout de convertir ma variable actuelle vers du char* car je ne peux pas faire :

Local<String> appName = args[0]->ToString(context).ToLocalChecked();

const char* var = appName; // ?

J’ai essayé d’utiliser c_str mais ma variable n’est pas de type string mais de type Local<String>.

char* appName = *args[0]->ToString(context).ToLocalChecked();

args.GetReturnValue().Set((int) FindWindowA(NULL, appName));

'initialisation' : impossible de convertir de 'T ' e n 'char '

Je n’ai jamais codé pour nodejs.

D’après ce que je comprend de la doc.

// Local<String>: args[0]->ToString(context).ToLocalChecked() 
// String: *args[0]->ToString(context).ToLocalChecked() 
// const char*: args[0]->ToString(context).ToLocalChecked()->c_str()

const char* appName = args[0]->ToString(context).ToLocalChecked()->c_str();

Ça fait longtemps que je n’ai pas codé en C++. J’espère ne pas être trop rouillé.

PS: Après relecture. C’est peut-être :

const char* appName = (*(args[0]->ToString(context).ToLocalChecked()))->c_str();

Ce qui est très moche. Plutôt passer par une variable intermédiaire.

String* strAppName = *(args[0]->ToString(context).ToLocalChecked());
const char* appName = strAppName->c_str();
+0 -0

Oui >_<" J’ai édité mon poste. ^^"

Et je viens de le ré-éditer pour rajouter des parenthèses… Ça fait décidément trop longtemps que je n’ai pas fait de C++.

Je me remettrais à jour avec le tutoriel du site.

Pour ma défense, je peux pas utiliser de compilateur, je fais tout de tête ^^"


Ah non mais oublie, c’est v8::String et pas std::String. Là j’abandonne.

+0 -0

Vos réponses m’ont aidé à reconsidérer un code que j’avais essayé :

  Local<String> appName = args[0].As<String>();

  char* charAppName = new char[128];
  (*appName)->WriteUtf8(isolate, charAppName);

  args.GetReturnValue().Set((int) FindWindowA(NULL, charAppName));

Savez vous si je peux trouver une application via le nom du processus au lieu du titre de la fenêtre ?

C’est un peu compliqué. Tout ça c’est de l’API Windows. Et ça remonte encore à très loin. Mais tu dois lister les processus et à partir de la tu pourras retrouver celui que tu veux.

A moins que je n’ai pas compris la question.

Regarde un peu par-là. winapi get a process handle

+0 -0

J’ai fais qui est censé retourné un array des éléments existant :

using v8::Array;
std::vector<int> GetProcessByName(PCSTR name) {
  std::vector<int> pids;
  INT i = 0;

  // Create toolhelp snapshot.
  HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  PROCESSENTRY32 process;
  ZeroMemory(&process, sizeof(process));
  process.dwSize = sizeof(process);

  // Walkthrough all processes.
  if (Process32First(snapshot, &process)) {
        std::cout << name << " \n";
    do {
      // Compare process.szExeFile based on format of name, i.e., trim file path
      // trim .exe if necessary, etc.
      if (std::string(process.szExeFile) == std::string(name)) {
        pids[i] = (int)process.th32ProcessID;
        i++;
      }
      std::cout << process.szExeFile << " \n";
    } while (Process32Next(snapshot, &process));
  }

  CloseHandle(snapshot);

  // Not found
  return pids;
}

static void isNaN(const FunctionCallbackInfo<Value>& args) {
  args.GetReturnValue().Set(args[0].As<Int32>()->Value() == NaN);
}

static void FindWindow(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  Local<String> appName = args[0].As<String>();

  CHAR* charAppName = new CHAR[128];
  (*appName)->WriteUtf8(isolate, charAppName);

  std::vector<int> pids = GetProcessByName(charAppName);

  Local<Array> array = Array::New(isolate, sizeof(pids));
  for(int i = sizeof(pids); i >= 0; i--) {
    array->Set(i++, Int32::New(isolate, pids[i]));
  }

  args.GetReturnValue().Set(array);
}
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte