Delphi:从导出接口/类的vc ++ dll调用函数 [英] Delphi: Calling a function from a vc++ dll that exports a interface / class

查看:201
本文介绍了Delphi:从导出接口/类的vc ++ dll调用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些麻烦访问由vc ++编写的dll导出一个接口。首先我试图使用类,但后一些google搜索我来到解决方案,这是我不可能。

i have some trouble accessing a dll written in vc++ that exports an interface. First i tried to use classes, but after some google-search i came to the solution, that this i not possible. I just want to make sure, that the plugin interface can accessed, by using other languages like c++.

Delphi接口

IPlugIn = interface
  function GetName: WideString; stdcall;
end;

Delphi插件调用

procedure TForm1.Button5Click(Sender: TObject);
var
  hLib: Cardinal; 
  MLoadPlugIn: TLoadPlugIn;
  PlugIn: IPlugIn;
begin
  hLib := LoadLibrary('PluginB.dll');
  try
    if not(hLib = 0) then
    begin
      @MLoadPlugIn := GetProcAddress(hLib, 'LoadPlugIn');
      if not(@MLoadPlugIn = nil) then
      begin
        if MLoadPlugIn(PlugIn) then
          try
            ShowMessage(PlugIn.GetName); // here i get the access-violation using the vc++ plugin
          finally                        // i get the return value but the instance is not created
            PlugIn := nil;
          end;
      end
      else
        raise Exception.Create('');
    end;
  finally
    FreeLibrary(hLib);
  end;
end;

Delphi插件dll

  TMyPlugin = class(TInterfacedObject, IPlugIn)
  public
    function GetName: WideString; stdcall;
  end;

function TMyPlugin.GetName;
begin
  result := 'TMyPlugin';
end;

function LoadPlugIn(var PlugIn: IPlugIn): Boolean; stdcall;
begin
  try
    PlugIn := TMyPlugin.Create;
    result := True;
  except
    result := False;
  end;
end;

exports
  LoadPlugIn;

vc ++ plugin dll

// IPlugIn

// IPlugIn

__interface //__declspec(uuid("E44BB34F-D13F-42D7-9479-4C79AF5C0D1B"))
IPlugIn : public IUnknown
{
 void _stdcall GetName(BSTR* result);
};

// TMyPlugIn标题

// TMyPlugIn header

class TMyPlugIn : public IPlugIn
{
public:
 // Constructor
 TMyPlugIn() : m_cRef(1) {}
 // Destructor
 ~TMyPlugIn() {}

 // Needed to implement IUnknown used by COM to acces your component
 HRESULT _stdcall QueryInterface(const IID& iid, void** ppv);
    ULONG _stdcall AddRef();
 ULONG _stdcall Release();

 void _stdcall GetName(BSTR* result);
private:
 long m_cRef ;
};

// TMyPlugIn cpp

// TMyPlugIn cpp

HRESULT _stdcall TMyPlugIn::QueryInterface(const IID& iid, void** ppv)
{    
 if (iid == IID_IUnknown)
 {
  *ppv = static_cast<IPlugIn*>(this) ; 
 }
 else if (iid == IID_IPlugIn)
 {
  *ppv = static_cast<IPlugIn*>(this) ;
 }
 else
 {
  *ppv = NULL ;
  return E_NOINTERFACE ;
 }
 reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
 return S_OK ;
}

ULONG _stdcall TMyPlugIn::AddRef()
{
 return InterlockedIncrement(&m_cRef) ;
}

ULONG _stdcall TMyPlugIn::Release() 
{
 if (InterlockedDecrement(&m_cRef) == 0)
 {
  delete this ;
  return 0 ;
 }
 return m_cRef ;
}

void _stdcall TMyPlugIn::GetName(BSTR* result)
{
 string s1 = "PluginName";
 *result = A2WBSTR(s1.c_str());
}

//从cpp插件导出函数

// the export function from the cpp plugin

extern "C" bool __declspec(dllexport) __stdcall LoadPlugIn(IPlugIn* PlugIn);
bool __declspec(dllexport) __stdcall LoadPlugIn(IPlugIn* PlugIn)
{
 PlugIn = new TMyPlugIn;
 return TRUE; 
}


推荐答案

此代码

extern "C" bool __declspec(dllexport) __stdcall LoadPlugIn(IPlugIn* PlugIn);
bool __declspec(dllexport) __stdcall LoadPlugIn(IPlugIn* PlugIn)
{
 PlugIn = new TMyPlugIn;
 return TRUE; 
}

创建一个插件类的实例并将地址写入堆栈,其中它很快就会被遗忘。回到Delphi程序中,原来的插件接口变量仍然是 nil ,所以调用一个方法崩溃。您需要模仿 QueryInterface()的作用,如下所示:

creates an instance of your plugin class and writes the address to the stack, where it quickly will be forgotten. Back in the Delphi program the original plugin interface variable is still nil, so calling a method on it crashes. You need to mimic what QueryInterface() does, like so:

extern "C" bool __declspec(dllexport) __stdcall LoadPlugIn(IPlugIn** PlugIn);
bool __declspec(dllexport) __stdcall LoadPlugIn(IPlugIn** PlugIn)
{
  *PlugIn = new TMyPlugIn;
  return TRUE; 
}

这会传递接口变量的地址并且插件实例的地址将被写入变量。

This passes the address of the interface variable, and the address of the plugin instance will be written to the variable.

这篇关于Delphi:从导出接口/类的vc ++ dll调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆