为什么我不能在为windows CE制作的MFC DLL中使用CString作为返回类型或参数



我有一个为桌面windows项目制作的库。它是由其他人在MFC VC++中完成的,并且工作正常。我将使用库中的一个特定函数作为示例来解释这种情况。

示例函数如下:

CString GetFulPath(); // .h file  

在cpp文件中,

CString CwFolderBrowser::GetFullPath()
{
CString path;
if(this->M_pIDLIST!=NULL)
{
LPTSTR fullPath=path.GetBuffer(MAX_PATH);
::SHGetPathFromIDList(this->M_pIDLIST, fullPath);   //ITEMIDLISTからパスを得る
path.ReleaseBuffer();
}
return path;
}

现在,我可以将这个库包含在我的项目中,并做一些类似的事情:

CwFolderBrowser cFolderBrowser;
if(cFolderBrowser.ShowDialog() == TRUE)
cPath = cFolderBrowser.GetFullPath();

这将显示一个文件夹浏览器对话框,让我选择一个文件夹。它在桌面窗口上运行良好。

目前,我正在使用Windows CE设备。我们已经通过删除不支持的函数和内容将库转换为与Windows CE一起使用。该库编译和构建正确无误。

接下来,我创建一个MFC智能设备项目,包括转换后的库、它的h文件和lib文件,并为dll设置正确的目录。这个项目建设得很好。我也可以#正确地包含库的h文件。

一旦我调用GetFullPath函数,问题就会出现:

cPath = cFolderBrowser.GetFullPath();  

它给了我一个未解决的外部链接错误!Intellisense确实在它的列表中显示了这个函数,我可以选择它和所有的东西。但徒劳无功。

奇怪的是,如果我修改库并更改GetFullPath()的签名,如下所示,

LPCTSTR GetFulPath(); // .h file  LPCTSTR instead of CString

在cpp文件中,

LPCTSTR CwFolderBrowser::GetFullPath()  // Return type changed to LPCTSTR  
{                                       // instead of CString 
...                                // Body modified accordingly
}

然后,未解决的外部链接错误消失,它工作!

我对这种奇怪的行为感到困惑,因为,我可以在MFC智能设备项目中正常使用CString,并且没有错误。只有当我尝试从库(以及其他类似库)dll调用函数时,链接错误才会出现。同时,BOOL、int等作为函数返回类型似乎没有问题。

当然,我可以遍历每个库,并将CString的每个实例更改为LPCTSTR,但这将是一个非常大的更改。我想知道为什么CString在项目中以及在桌面上的dll中都能很好地工作,而在Win CE上,它在项目中却不能在dll中工作(同时,无论是使用CString还是LPCTSTR,dll本身都能编译得很好,没有错误!)。

因此,基本上,如果可能的话,我想保留函数CString,并想知道发生这种情况的原因。完全相同的错误也发生在其他库中。

感谢您的帮助。非常感谢。

更新:我在ATL&MFC 7.0,其中谈到了使用/Zc:wchat_t选项。我已经检查了Dll项目以及我的应用程序。两者都使用相同的选项"将wchar_t视为内置类型"作为"是"。所以,这个选项是匹配的。此外,如上所述,将函数返回更改为LPCTSTR是可行的。错误消失。在我将返回的LPCTSTR转换回CString之前,一切都很顺利。CString结果为空/Null。这既发生在dll代码本身中,也发生在我的应用程序代码中。

更新2:多亏了Michael和Cody,我将函数更改为LPCTSTR,并确保这些值不会超出范围,然后才能按照他们的建议使用它们。现在空/空问题解决了,我可以正确地获取路径值。

剩下的问题是,我必须将所有的CString函数转换为LPCTSTR,这并不完全可行我想将函数保留为CString

这是一个经典的问题,在SO上经常被问到。

这不起作用:

LPCTSTR CwFolderBrowser::GetFullPath()
{
CString path;
if(this->M_pIDLIST!=NULL)
{
LPTSTR fullPath=path.GetBuffer(MAX_PATH);
::SHGetPathFromIDList(this->M_pIDLIST, fullPath);  
path.ReleaseBuffer();
}
return (LPCTSTR)path;  // << here you return a pointer to the zero 
//    terminated string in the path object,  
}                          //    but path will be deleted as soon as it goes
//    out of scope

在某些情况下,该函数似乎可以工作,因为已删除的CString对象的内存尚未被覆盖。

你应该这样做(为了简单起见,这里没有错误处理):

LPCTSTR CwFolderBrowser::GetFullPath(TCHAR *pathbuffer)
{
if(this->M_pIDLIST!=NULL)
{
::SHGetPathFromIDList(this->M_pIDLIST, pathbuffer);  
}
return (LPCTSTR)pathbuffer;
}
...
// call like this
TCHAR pathbuffer[MAX_PATH];
GetFullPath(pathbuffer);

最新更新