2

我正在将现有的(主要是)跨平台应用程序移植到 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

4 回答 4

5

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

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

如果您的切入点是这样的:

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

然后将入口点设置为mainACRTStartup

但如果你开始:

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

那么入口点是mainWCRTStartup

于 2010-10-19T15:40:32.603 回答
2

您的一般想法是正确的,但是您转换 lpCmdLine 可能会给您带来一些问题。考虑以下:

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

传递给您的主函数的参数将是这样的:

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

于 2009-01-12T07:37:59.770 回答
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(因为我是 new char[]'d),但是当我这样做时,程序出现了致命错误。当我切换到上述内容时,它起作用了。这不违反 new->delete/new[]->delete[] 规则吗?

于 2009-01-13T05:26:35.417 回答
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;
}
于 2009-01-12T07:56:23.930 回答