正常以WinCE为主

时间:2009-01-12 07:23:24

标签: c++ windows-ce evc4

我正在将现有(主要)跨平台应用程序移植到WinCE 4.2。该函数的当前入口点是

int main(int argc, char *argv[]){}

我想按原样保留此部分,并让WinCE入口点简单地调用它。我相信以下内容应该有效:

int WINAPI WinMain( HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPTSTR    lpCmdLine,
                    int       nCmdShow) 
{
    int argc = _tcslen(lpCmdLine);
    char *argv = new char[argc];
    wcstombs(argv,lpCmdLine,1024);
    argc = main(argc,&argv);
    delete [] argv;
    return argc;
}

它编译,并且应该运行一次我弄清楚链接器为什么会抛出,但是它是对的吗?

4 个答案:

答案 0 :(得分:5)

真正简单的方法是只更改项目的链接器入口点并使用main(...)函数。

打开项目属性对话框,然后转到“Linker-> Advancedd”并根据以下内容设置“入口点”值:

如果您的切入点是:

int main(int argc, char *argv[])

然后将入口点设置为mainACRTStartup

但是,如果您从以下开始:

int _tmain(int argc, TCHAR *argv[])

然后输入点为mainWCRTStartup

答案 1 :(得分:2)

您的一般想法是正确的,但是您转换lpCmdLine可能会导致一些问题。请考虑以下事项:

$> myprogam.exe -a shortargument -b -c -d“带有空格的长参数”

传递给你的main函数的参数将是这样的:

argc = 7;
argv = {
    "myprogram.exe",
    "-a",
    "shortargument",
    "-b",
    "-c",
    "-d",
    "long argument with spaces"
};

WinMain会收到一个像这样的长字符串:

lpCmdLine = "-a shortargument -b -c -d "long argument with spaces"";

因此,如果您正在进行任何命令行选项解析,那么您可能会破坏它。最通用的方法是循环通过lpCmdLine将所有空格(当然在匹配引号之外)设置为空字符(即'\ 0'或简单地为0)并跟踪指向第一个有效字符的指针。空字符序列。

添加:如果我从wince开发的时候正确地回忆起来,我似乎记得有关lpCmdLine的一些内容,因为它与win32兼容,所以它总是空的。要获得命令行,我认为您必须使用GetCommandLine

答案 2 :(得分:2)

谢谢你们的有用答案。我写了以下内容,它现在和我们需要的一样有效。只有我们的代码将调用此可执行文件,并且从不使用引号,尽管这不会太难添加。此外,如果参数之间有多个空格,它可能不会很好,但同样,我们不必担心其他人使用此程序,它只是出于学术目的。如果您认为有必要进行改进,请编辑此帖子,并在评论中证明其合理性。

int WINAPI WinMain( HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPTSTR    lpCmdLine,
                    int       nCmdShow ) {
  assert(lpCmdLine != NULL);

  int argc = 1, ret = 0;
  std::vector<char*>  args;

  // Copy the entire array to a regular cstr
  int cmdLineLen = _tcslen(lpCmdLine);
  char *argv = new char[cmdLineLen];
  wcstombs(argv,lpCmdLine,cmdLineLen);
  args.push_back(&argv[0]);

  // Replace spaces with nulls to effectively create array of cstr
  for(int i=0; i<cmdLineLen; i++){
    if(argv[i] == ' '){
      argv[i] = '\0';
      args.push_back(&argv[i+1]); // Keep track of the first char in each word
      argc++;
    }
  }

  // argv[argc] should be NULL. 
  args.push_back(NULL);

  try{ // Run the program
    ret = main(argc,&args[0]);
  }
  catch(...){
    // TODO: Report error here. Commented code works OK for WinCE .NET
    // delete argv;
    // throw; 
    ret = -1;
  }
  delete argv;
  return ret;
}

另外,对于那些感兴趣的人,在命令行运行它

>myprogam.exe -a shortargument -b -c

将以下内容放入lpCmdLine

"-a shortargument -b -c"

另外,我的第一个猜测是argv需要删除[]'d(因为我新的char []'d),但是当我这样做时,该程序有一个致命的错误。当我切换到上面时,它工作。这是否违反了新的&gt;删除/新[] - &gt;删除[]规则?

答案 3 :(得分:1)

不,这不起作用。

int WINAPI WinMain( HINSTANCE hInstance,
                HINSTANCE hPrevInstance,
                LPTSTR    lpCmdLine,
                int       nCmdShow) 
{
    // argc: This is the number of arguments NOT the strlen
    int argc = _tcslen(lpCmdLine);

    // argv: Is an array of char* NOT an array of char.
    char *argv = new char[argc];
    wcstombs(argv,lpCmdLine,1024);

    // The argument passed as argc is not valid here.
    argc = main(argc,&argv);
    delete argv;

    // You are returning the result of main that is correct.
    // But re-using argc like this is smelly. Declare a new
    // variable and let the compiler optimise away the extra use
    // the compiler is VERY good at that.
    return argc;
}

行。不是WinCE的专家。 如果我这样做,我会使用std :: vector你可以修改工作

int WINAPI WinMain( HINSTANCE hInstance,
                HINSTANCE hPrevInstance,
                LPTSTR    lpCmdLine,
                int       nCmdShow) 
{
    std::vector<char*>  args;

    // Split lpCmdLine by space.
    // Remember to watch for quotes when splitting (From 'Kevin Loney')
    // For each argument do
    args.push_back(<SOMTHING>)


    // The last argv[argc] should be NULL. 
    args.push_back(NULL);

    int result;
    try
    {
        // argc does not include the last NULL so do a -1
        result = main(args.size()-1,&args[0]);
    }
    catch(...)
    {
        // If <SOMTHING> includes dynamically allocating memory
        // Then you should delete it here.

        throw;  // Re-Throw the exception to get the same behavior.
    }

    return result;
}