草庐IT

c++ - VS COM 项目在 32 位编译但在尝试编译 64 位时抛出错误 C2259

coder 2024-02-11 原文

您好,我目前正在运行 Visual Studio 2010,并且有一个上下文菜单 shell 扩展在 32 位机器上完全以 32 位运行,因此所有方法都存在。这是一个 ATL 项目。 32 位上没有错误甚至警告。

问题来了。当我进入 visual studio 下的配置管理器并将事件解决方案平台从 Win32 切换到 x64 并尝试编译时,我收到错误“错误 C2259:'ATL::CCOMObject:无法实例化抽象类”。

既然这个完全相同的项目确实在 32 位编译和运行,为什么它会抛出 x64 的错误?

任何想法或正确方向的观点将不胜感激。
需要实现的主要方法如下:

STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
STDMETHODIMP GetCommandString(UINT, UINT, UINT*, LPSTR, UINT);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT);

保存代码空间创建一个 Atl 项目。创建初始项目后,添加一个新类“TestingContextMenu”,其余代码将引用它。

stdafk.h

#include "resource.h"
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <shlobj.h>
#include <comdef.h>

#include <string>
#include <list>
typedef std::list< std::basic_string<TCHAR> > string_list;

TestingContextMenu.h 仅包含已添加/更改的部分

#include "stdafx.h"
using namespace std;
class ATL_NO_VTABLE CTestingContextMenu:
        public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CTestingContextMenu, &CLSID_TestingContextMenu>,
    public IShellExtInit,
    public IContextMenu
    {
        // Comment out or remove IDispatch
BEGIN_COM_MAP(CMainMagnimbusContextMenu)
    //COM_INTERFACE_ENTRY(ITestingContextMenu)
    //COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IShellExtInit)
    COM_INTERFACE_ENTRY(IContextMenu)
END_COM_MAP()

protected:
    TCHAR m_szFile[MAX_PATH];
    list<string> Filenames;
    list<string> FilenamesCopier;
public:
    STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);

    STDMETHODIMP GetCommandString(UINT, UINT, UINT*, LPSTR, UINT);
    STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
    STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT);
};  //There is other code within this but it is autogenerated

TestingContextMenu.cpp

#include "stdafx.h"
#include "TestingContextMenu"
#include <sstream>
using namespace std;
#pragma comment(lib, "comsuppw")

STDMETHODIMP CMainMagnimbusContextMenu::Initialize ( 
  LPCITEMIDLIST pidlFolder,
  LPDATAOBJECT pDataObj,
  HKEY hProgID )
  {
  FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    STGMEDIUM stg = { TYMED_HGLOBAL };
    HDROP     hDrop;

    if ( FAILED( pDataObj->GetData ( &fmt, &stg ) ))
        return E_INVALIDARG;
    hDrop = (HDROP) GlobalLock ( stg.hGlobal );

    UINT uNumFiles = DragQueryFile ( hDrop, 0xFFFFFFFF, NULL, 0 );
   HRESULT hr = S_OK;

   if ( 0 == uNumFiles )
    {
       GlobalUnlock ( stg.hGlobal );
       ReleaseStgMedium ( &stg );
       return E_INVALIDARG;
    }

   UINT counter = 0;
    // Get the name of the every file and store it in our member variable m_szFile.
   for(counter = 0; counter < uNumFiles; counter++)
   {
        if ( 0 == DragQueryFile ( hDrop, counter, m_szFile, MAX_PATH ) )
        {   
            hr = E_INVALIDARG;
        }
        wchar_t* t = _wcsdup(m_szFile);
        char ch[260];
        char DefChar = ' ';
        WideCharToMultiByte(CP_ACP,0,t,-1, ch,260,&DefChar, NULL);
        string ss(ch);
        Filenames.push_back(ss);
        FilenamesCopier.push_back(ss);
   }

   GlobalUnlock ( stg.hGlobal );
   ReleaseStgMedium ( &stg );

   return hr;
}

其余功能可根据要求提供。但是我注意到了一些新的东西。如果您只实现了上述功能和代码,并且配置管理器设置为构建 x64,您将得到我遇到的初始错误。这甚至意味着不执行 QueryContextMenu、GetCommandString 或调用命令。使用此设置唯一会出现的错误是我的原始错误,这是我们所期望的,因为它们没有实现。然而,将该配置管理器切换回 Win32,您会得到预期的错误,例如 3 个 Unresolved external 错误,以及 3 个错误,其后命名为 GetCommandString、InvokeCommand 和 QueryContextMenu。再次期望它们是否未实现,但为什么 x64 上的编译器只识别我的原始错误,这是很多人认为的错误,而不是已实现的方法,但在 win32 集上,它在未实现时显示完整错误。

上一段只是我注意到的。我确实在 Win32 中正确实现了所有 3 种方法并正确编译,但在 x64 中却没有。

最佳答案

您的 GetCommandString 参数与接口(interface)方法定义的参数不匹配。

你的

STDMETHODIMP GetCommandString(UINT, UINT, UINT*, LPSTR, UINT)

需要

STDMETHODIMP GetCommandString(UINT_PTR, UINT, UINT*, LPSTR, UINT)

Win32 中,不匹配不是那么重要(参数类型解析为同一类型),而在 x64 中变得很重要。编译器构建输出应该已经为您提供了提示,包括缺少的方法名称。

关于c++ - VS COM 项目在 32 位编译但在尝试编译 64 位时抛出错误 C2259,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11768016/

有关c++ - VS COM 项目在 32 位编译但在尝试编译 64 位时抛出错误 C2259的更多相关文章

  1. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  6. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  7. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  8. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  9. ruby - Sinatra set cache_control to static files in public folder编译错误 - 2

    我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.

  10. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

随机推荐