被一个com搞的晕头转向。。。。

draculamx 2020-07-10 02:06:18
有一个com是dll文件,注册,使用,都没问题,但是我用到其中一个函数的时候,始终无法运行。
dll文件,通过“Component”--"Import Component"方式导入,所以自动生成了xxxx_TLB.h和xxxx_TLB.cpp

在xxxx_TLB.h中,有这样一个函数和接口:

//这是我要调用的函数,这个函数的最后一个参数,就是我出问题的地方,它需要下面那个接口的指针
HRESULT __fastcall EncodeFile(BSTR FileName/*[in]*/, BSTR
OutputFileName/*[in]*/,
BSTR Parameters/*[in]*/,
unsigned ResampleSampleRate/*[in]*/,
unsigned Channels/*[in]*/,
double StartPosition/*[in]*/,
double Length/*[in]*/,
double Normalize/*[in]*/,
Bassencoder_tlb::IProgress* ProgressCallback/*[in]*/);

//这是接口
// *********************************************************************//
// Interface: IProgress
// Flags: (4352) OleAutomation Dispatchable
// GUID: {C23CF58D-3121-45D2-A0DB-B19F98350D52}
// *********************************************************************//
interface IProgress : public IDispatch
{
public:
HRESULT STDMETHODCALLTYPE ProgressCallback(double Progress/*[in]*/); // [201]
};


然后我创建一个窗体,在窗体的头文件 Form1.hpp中,我改写了窗口类的派生关系

“class TFormMain : public TForm”

改为
“class TFormMain : public TForm ,public IProgress”


接着我重写了“IProgress ”接口中的“ProgressCallback”函数

HRESULT STDMETHODCALLTYPE TFormMain::ProgressCallback(double Progress)
{
pb1->Position=(int)(Progress);
return S_OK;
}

然后我调用这个函数:
EncodeFile(.............(IProgress*)this);


运行结果“Pure virtual function called”。。。。。

我尝试了一些修改
第一种,把重写的函数类改为基类,如下:

HRESULT STDMETHODCALLTYPE IProgress::ProgressCallback(double Progress)
{
//pb1->Position=(int)(Progress);
return S_OK;
}


第二种
EncodeFile(.............(IProgress*)this);

改为
EncodeFile(.............this);



两种都不行。。其实这个代码是照着DEMO中,DELPHI的例子来的,DELPHI运行完全没有问题。。。
搞了一天了,不行了,大家帮忙看看。。。




...全文
400 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
draculamx 2020-07-20
  • 打赏
  • 举报
回复
算了,不纠结了,我直接发邮件给了作者,作者居然回复了,他自己说他C++也不怎么会用,然后他就给修改了一个直接调用callback函数,不通过interface的方法。。就像我们平时调用一些函数时,需要用到的回调函数一样,直接丢一个函数指针进去就行了,我试了下,可用。。。。
  • 打赏
  • 举报
回复
试一试:
EncodeFile(.............interface_cast<IProgress>(this));
Waiting4you 2020-07-19
  • 打赏
  • 举报
回复
奇怪,按理说你继承这个COM接口你要实现IUnknown, IDispatch的函数,你的代码里没看到。编译居然能通过~~可能C++Builder有什么机制帮忙实现了这些? 你试试这样行不行: TComInterface<IProgress> tmp(this); EncodeFile(..., tmp); 如果在TComInterface这句出错,调试步进去看看是不是QueryInterface这里挂了,如果确实,说明你需要自己实现这个函数。
  • 打赏
  • 举报
回复
如果把
EncodeFile(.............(IProgress*)this);
改成
EncodeFile(.............(IProgress*)FormMain);
丁劲犇 2020-07-17
  • 打赏
  • 举报
回复
你用了多重继承,不要直接强制转换指针。 把转换去掉应该就好了。或者调用dynamic_cast (IProgress*)this 你那个强行转换不对。 先试试直接给this,应该就可以
draculamx 2020-07-14
  • 打赏
  • 举报
回复
引用 11 楼 早打大打打核战争 的回复:
HRESULT _fastcall ProgressCallback(double Progress); 这个地方应该是__stdcall
开始是用的 __stdcall,后来不断尝试,司马当活马医才这样改的。。。用__stdcall也不行。。
  • 打赏
  • 举报
回复
HRESULT _fastcall ProgressCallback(double Progress);
这个地方应该是__stdcall
draculamx 2020-07-13
  • 打赏
  • 举报
回复
引用 9 楼 ooolinux 的回复:
IBASSEncodeFile *BASSEncodeFileMP3; 指针试试呢
我觉得并不是函数调用的问题,因为我前面说了,把这个函数的最后一个参数,设置为NULL,函数功能和整个程序都是正常的,没有任何问题。问题就出在最后一个参数上。 还有就是在C++中如何去把继承来的接口(Interface,实则为struct)里面的那个函数给实现。 现在从返回的错误来看,提示我调用了一个纯虚函数,也就是函数只有声明,没有实现,但是从代码来看,我继承了这个接口以后,是实现了这个函数的。。
ooolinux 2020-07-13
  • 打赏
  • 举报
回复
IBASSEncodeFile *BASSEncodeFileMP3; 指针试试呢
draculamx 2020-07-13
  • 打赏
  • 举报
回复
BASSEncodeFileMP3.EncodeFile函数的最后一个参数,是可以设置为NULL的,即不接收进度信息 当最后一个参数为NULL的时候,函数是可以正常运行的,没有任何问题 也就是最后一个参数的问题,到底是什么问题,继承接口重写函数没有覆盖接口“IProgress”的函数??“IProgress”接口中的那个函数,还是没有被实现??依然只有一个声明??但是从代码来看,我先用“TFormMain”继承了“IProgress”接口,然后在“TFormMain”中,定义并实现了和“IProgress”接口中的同名的函数,所以接口“IProgress”的函数声明应该被隐藏了啊。。 况且Delphi的代码也是这么做的,为什么它可以运行?难道Delphi在接口继承方面和CB有不同?? 最后,我将代码简化以后,在VS2019里面也可以运行的。。。
draculamx 2020-07-13
  • 打赏
  • 举报
回复
我来把问题简化一下吧: CB中,代码如下: 头文件

class TFormMain : public TForm,public IProgress
{
__published:	// IDE-managed Components
	TButton *btn1;
	TProgressBar *pb1;
	void __fastcall FormCreate(TObject *Sender);
	void __fastcall btn1Click(TObject *Sender);
	void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
private:	// User declarations
	HRESULT _fastcall ProgressCallback(double Progress);
public:		// User declarations
	__fastcall TFormMain(TComponent* Owner);

};

//---------------------------------------------------------------------------
extern PACKAGE TFormMain *FormMain;
源文件:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "FormMainUnit.h"

//----------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormMain *FormMain;


HRESULT _fastcall TFormMain::ProgressCallback(double Progress)
{
	//pb1->Position=(int)(Progress);
	return S_OK;
}


//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
	: TForm(Owner)
{

}

void __fastcall TFormMain::btn1Click(TObject *Sender)
{
    IBASSEncodeFile BASSEncodeFileMP3;
    HResult Error;
    //* Acquire the class
    BASSEncodeFileMP3 = (IBASSEncodeFile)CreateComObject(CLASS_TBASSEncodeFileMP3);
    //* Generate MP3, CBR 320 kbps, 44100 Hz, 2 channels (stereo)
    Error = BASSEncodeFileMP3.EncodeFile(EditInputFileName->Text, EditOutputFileName->Text, "-b 320", 44100, 2, 0, 0, 0, this);
}

CB中的代码就这些,Delphi可以运行的例子,全部代码就在上面4楼,现在的问题就是,CB运行会报错:“Pure virtual function called”。。。。。 搜索了一些相关资料,没有得到答案
draculamx 2020-07-13
  • 打赏
  • 举报
回复
引用 5 楼 早打大打打核战争 的回复:
var BASSEncodeFileMP3: IBASSEncodeFile; Error: HResult; begin //* Acquire the class BASSEncodeFileMP3 := CreateComObject(CLASS_TBASSEncodeFileMP3) as IBASSEncodeFile; //* Generate MP3, CBR 320 kbps, 44100 Hz, 2 channels (stereo) Error := BASSEncodeFileMP3.EncodeFile(EditInputFileName.Text, EditOutputFileName.Text, '-b 320', 44100, 2, 0, 0, 0, Self); 如果按照这个改写: IBASSEncodeFile BASSEncodeFileMP3; HResult Error; //* Acquire the class BASSEncodeFileMP3 = (IBASSEncodeFile)CreateComObject(CLASS_TBASSEncodeFileMP3); //* Generate MP3, CBR 320 kbps, 44100 Hz, 2 channels (stereo) Error = BASSEncodeFileMP3.EncodeFile(EditInputFileName->Text, EditOutputFileName->Text, "-b 320", 44100, 2, 0, 0, 0, this);
我在一楼就提到过,我就是这么写的。。得到的运行结果是:“Pure virtual function called”。。。。
  • 打赏
  • 举报
回复
var
BASSEncodeFileMP3: IBASSEncodeFile;
Error: HResult;
begin
//* Acquire the class
BASSEncodeFileMP3 := CreateComObject(CLASS_TBASSEncodeFileMP3) as IBASSEncodeFile;
//* Generate MP3, CBR 320 kbps, 44100 Hz, 2 channels (stereo)
Error := BASSEncodeFileMP3.EncodeFile(EditInputFileName.Text, EditOutputFileName.Text, '-b 320', 44100, 2, 0, 0, 0, Self);

如果按照这个改写:
IBASSEncodeFile BASSEncodeFileMP3;
HResult Error;
//* Acquire the class
BASSEncodeFileMP3 = (IBASSEncodeFile)CreateComObject(CLASS_TBASSEncodeFileMP3);
//* Generate MP3, CBR 320 kbps, 44100 Hz, 2 channels (stereo)
Error = BASSEncodeFileMP3.EncodeFile(EditInputFileName->Text, EditOutputFileName->Text, "-b 320", 44100, 2, 0, 0, 0, this);
draculamx 2020-07-13
  • 打赏
  • 举报
回复

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, BASSEncoder_TLB, Vcl.ComCtrls;

type
  TForm1 = class(TForm, IProgress)
    Button2: TButton;
    GroupBox1: TGroupBox;
    Button3: TButton;
    Label1: TLabel;
    EditInputFileName: TEdit;
    Button4: TButton;
    EditOutputFileName: TEdit;
    Label2: TLabel;
    Button5: TButton;
    Label3: TLabel;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    ProgressBar1: TProgressBar;
    Button1: TButton;
    Button6: TButton;
    Button7: TButton;
    Button8: TButton;
    Label4: TLabel;
    EditCommandLine: TEdit;
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    //procedure Button9Click(Sender: TObject);
  private
    { Private declarations }
    function ProgressCallback(Progress: Double): HResult; stdcall;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Uses
    //BASSEncoderLibrary,
    ComObj;

//* Example to call the DLL class directly without COM (requires BASSEncoderLibrary.pas in the Uses list):
{
procedure TForm1.Button9Click(Sender: TObject);
var
    BASSEncodeFileMP3: IBASSEncodeFile;
    Error: HResult;
begin
    //* Acquire the class
    BASSEncodeFileMP3 := BASSEncoderGetFileMP3;
    //* Generate MP3, CBR 320 kbps, 44100 Hz, 2 channels (stereo)
    Error := BASSEncodeFileMP3.EncodeFile(EditInputFileName.Text, EditOutputFileName.Text, '-b 320', 44100, 2, 0, 0, 0, Self);
    if Error <> 0 then begin
        Showmessage('Error: ' + IntToStr(Error));
    end;
end;
}
procedure TForm1.Button7Click(Sender: TObject);
var
    BASSEncodeFileMP3: IBASSEncodeFile;
    Error: HResult;
begin
    //* Acquire the class
    BASSEncodeFileMP3 := CreateComObject(CLASS_TBASSEncodeFileMP3) as IBASSEncodeFile;
    //* Generate MP3, CBR 320 kbps, 44100 Hz, 2 channels (stereo)
    Error := BASSEncodeFileMP3.EncodeFile(EditInputFileName.Text, EditOutputFileName.Text, '-b 320', 44100, 2, 0, 0, 0, Self);
    if Error <> 0 then begin
        Showmessage('Error: ' + IntToStr(Error));
    end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
    BASSEncodeFileOpus: IBASSEncodeFile;
    Error: HResult;
begin
    //* Acquire the class
    BASSEncodeFileOpus := CreateComObject(CLASS_TBASSEncodeFileOpus) as IBASSEncodeFile;
    //* Generate Opus, 320 kbps
    Error := BASSEncodeFileOpus.EncodeFile(EditInputFileName.Text, EditOutputFileName.Text, '--bitrate 320', 0, 0, 0, 0, 0, Self);
    if Error <> 0 then begin
        Showmessage('Error: ' + IntToStr(Error));
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
    BASSEncodeFileFLAC: IBASSEncodeFile;
    Error: HResult;
begin
    //* Acquire the class
    BASSEncodeFileFLAC := CreateComObject(CLASS_TBASSEncodeFileFLAC) as IBASSEncodeFile;
    //* Generate FLAC
    Error := BASSEncodeFileFLAC.EncodeFile(EditInputFileName.Text, EditOutputFileName.Text, '--best', 0, 0, 0, 0, 0, Self);
    if Error <> 0 then begin
        Showmessage('Error: ' + IntToStr(Error));
    end;
end;

procedure TForm1.Button6Click(Sender: TObject);
var
    BASSEncodeFileOggVorbis: IBASSEncodeFile;
    Error: HResult;
begin
    //* Acquire the class
    BASSEncodeFileOggVorbis := CreateComObject(CLASS_TBASSEncodeFileVorbis) as IBASSEncodeFile;
    //* Generate Ogg Vorbis, 320 kbps
    Error := BASSEncodeFileOggVorbis.EncodeFile(EditInputFileName.Text, EditOutputFileName.Text, '--bitrate 320', 0, 0, 0, 0, 0, Self);
    if Error <> 0 then begin
        Showmessage('Error: ' + IntToStr(Error));
    end;
end;

procedure TForm1.Button8Click(Sender: TObject);
var
    BASSEncodeFileCommandLine: IBASSEncodeFile;
    Error: HResult;
begin
    //* Acquire the class
    BASSEncodeFileCommandLine := CreateComObject(CLASS_TBASSEncodeFileCommandLine) as IBASSEncodeFile;
    //* Encode a MusePack file (replace '{outputfilename}' with specified output file name and convert extension to .mpc)
    Error := BASSEncodeFileCommandLine.EncodeFile(EditInputFileName.Text, ChangeFileExt(EditOutputFileName.Text, '.mpc'), StringReplace(EditCommandLine.Text, '{outputfilename}', '"' + ChangeFileExt(EditOutputFileName.Text, '.mpc') + '"', [rfReplaceAll]), 0, 0, 0, 0, 0, Self);
    if Error <> 0 then begin
        Showmessage('Error: ' + IntToStr(Error));
    end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
    Close;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
    OpenDialog1.FileName := EditInputFileName.Text;
    if OpenDialog1.Execute then begin
        EditInputFileName.Text := OpenDialog1.FileName;
    end;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
    SaveDialog1.FileName := EditOutputFileName.Text;
    if SaveDialog1.Execute then begin
        EditOutputFileName.Text := SaveDialog1.FileName;
    end;
end;

function TForm1.ProgressCallback(Progress: Double): HResult; stdcall;
begin
    ProgressBar1.Position := Round(Progress);
    Result := S_OK;
end;

end.

这是Delphi例子的所有代码,就这些,我觉得我C++ Builder里面的代码和这个应该没有什么出入,但就是运行不了。。
  • 打赏
  • 举报
回复
既然运行结果不一样,翻译肯定是没有完全一致
draculamx 2020-07-11
  • 打赏
  • 举报
回复
delphi的例子,就是和我一样的,或者说,我这代码就是delphi翻译过来的
  • 打赏
  • 举报
回复
Delphi的例子是怎样调用的

703

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder ActiveX/COM/DCOM
社区管理员
  • ActiveX/COM/DCOM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧