2017-04-21 100 views
0

我需要用C++编写一个DLL,其中包含一些稍后在VBA中使用的函数。为什么我的VBA没有在C++ DLL中找到函数?

我写这个样子的(不过,我承认我一直在从互联网上的一些例子复制,因为我很到C++,我不知道我需要 .h文件所有这些东西):

// FieldTrans.h 

#ifndef FIELDTRANS 
#ifdef _WIN32 
#ifdef BUILD_DLL 
#define FIELDTRANS_FUNC __declspec(dllexport) 
#else 
#define FIELDTRANS_FUNC __declspec(dllimport) 
#endif 
#define FIELDTRANS_FUNC 
#else 
#define FIELDTRANS_FUNC __attribute__ ((visibility("default"))) type 
#endif 

// Returns the interpolated field matrix: 180° x 360° with Res step 
FIELDTRANS_FUNC double ShannonInterp(double* Matrix, double Res, double DeltaTheta, double DeltaPhi); 
// Returns the normalized cardinal sinus coefficient 
FIELDTRANS_FUNC double SpecialLog(double x); 
#endif 

虽然.cpp文件中包含这些功能的实际定义:

// FieldTrans.cpp 

#include "stdafx.h" 
#include "FieldTrans.h" 
#include <array>   // for counting elements of an array 
#define _USE_MATH_DEFINES // for M_PI 
#include <math.h>   // for M_PI and Log10 

using namespace std; 

double SinC(double x) 
{ 
    if (x == 0) 
    { 
     return 1; 
    } 
    else 
    { 
     return sin(M_PI * x)/(M_PI * x); 
    } 
} 

double ShannonInterp(double *Matrix[], double Res, double DeltaTheta, double DeltaPhi) 
{ 
    int k, l, m, n; 
    double iRes, jRes; 
    double ThetaSinC, PhiSinC; 
    int MatrixHeigth = sizeof(Matrix)/sizeof(Matrix[0]), MatrixWidth = sizeof(Matrix[0])/sizeof(Matrix); 
    int Height = 180/Res, Width = 360/Res; 
    double *Interpolated = new double[Height * Width]; 
    k = 0; 
    m = 1; 

    for (int i = 0; i < Height; i++) 
    { 
     iRes = i * Res; 
     do 
     { 
      k = k + 1; 
      m = k + 1; 
     } while (iRes > (k + 1) * DeltaTheta); 
     if (m > MatrixHeigth) 
     { 
      m = MatrixHeigth - 1; 
     } 
     ThetaSinC = SinC((iRes - k * DeltaTheta)/DeltaTheta); 
     l = 0; 
     n = 1; 
     for (int j = 0; j < Width; j++) 
     { 
      jRes = j * Res; 
      do 
      { 
       l = l + 1; 
       n = l + 1; 
      } while (jRes > (l + 1) * DeltaPhi); 
      if (n > MatrixWidth) 
      { 
       n = 0; 
      } 
      PhiSinC = SinC((jRes - l * DeltaPhi)/DeltaPhi); 
      Interpolated[i * Width + j] = Matrix[k][l] * ThetaSinC * PhiSinC + Matrix[k][n] * ThetaSinC * (1 - PhiSinC) + Matrix[m][l] * (1 - ThetaSinC) * PhiSinC + Matrix[m][n] * (1 - ThetaSinC) * (1 - PhiSinC); 
     } 
    } 
    return *Interpolated; 
} 

我很肯定,在.cpp部分工作得很好。 我使用Visual Studio创建了一个DLL,并通过修改“Multithreaded-DLL(/ MD)”选项之一来使用“Project” - “Project properties” - “C/C++” - “Code generation”。 的DLL已经建立之后,我写了下面的代码在我的VBA程序:

Private Declare Function Shannonize Lib "C:\Users\daquino\Documents\Visual Studio 2013\Projects\FieldTrans\Release\FieldTrans.dll" Alias _ 
         "ShannonInterp" (ByRef Matrix() As Double, ByVal Res As Double, ByVal DeltaTheta As Double, ByVal DeltaPhi As Double) As Double 

但它不工作,因为当我使用的功能,它说,它不能在模块中找到。我使用的功能是这样的:

InterpCo = Shannonize(AmplCo, Resolution, 181/(PointsTheta+1), 361/(PointsPhi+1)) 

提供AmplCo是双的2D阵列,和其他的输入是整数。

你能帮我理解有什么问题吗?

编辑:如果我尝试从我的VBA程序中插入对.dll的引用,它会显示“引用错误”。

+0

使用dumpbin或Dependency Walker检查DLL的导出。 –

+1

有很多错误。 C++编译器装饰函数的名字以支持重载,你必须用'extern“C”'来关闭它。调用约定是错误的,你必须使用'__stdcall'。 VBA希望将数组编组为“SAFEARRAY”。你不能添加引用,这不是一个COM服务器,Declare就是你所拥有的。迈出一小步去那里,不要试图用一个巨大的口水做这一切,否则你将不可避免地陷入困境。有大量的网页显示如何做到这一点。 –

+0

我一直在阅读各种东西2天,是的,虽然我同意,我不应该在吞下一个时间整个事情,我还是希望* *做到这一点。也许我很愚蠢,但是我没有找到类似于我需要做的事情的例子。即使'extern'也不能按照它应有的方式工作,如果我在头文件*和* che文件中使用它,@VTT指出 – Noldor130884

回答

1

它看起来像从dll导出的C++函数的名称已被损坏。与C不同的是,C++函数可以被重载(同名但参数不同),可以驻留在命名空间等中,因此导出函数的名称也会包含一些额外的后缀。您可以使用extern "C" { /*your code*/ }块来环绕导出的函数,以防止名称变形或使用适当的命名编写模块导出文件(.def)。

+0

在标题中还是在cpp中?你能写一个例子吗? – Noldor130884

+0

在标题和cpp中。 – VTT

+0

如果我这样做的似乎工作的头,但如果我那么做的CPP不 – Noldor130884

相关问题