2009-01-24 141 views
2

我的问题是了解混合语言编程 和访问外部库中API的更精细的点。我的C++技能不存在 和VB,平庸。混合语言编程,VB和C++,了解API和指针

我有一个C++ dll编译(portaudio库),并试图从VB (Visual Studio 2005)访问它。 我调用函数时出现MarshallDirectiveException错误,我相信因为 我与dll的错误交互。


C++函数和结构的定义如下:

头信息:

typedef int PaHostApiIndex; 
... 
typedef double PaTime; 
... 
typedef struct PaDeviceInfo 
{ 
    int structVersion; /* this is struct version 2 */ 
    const char *name; 
    PaHostApiIndex hostApi; /* note this is a host API index, not a type id*/ 
    int maxInputChannels; 
    int maxOutputChannels; 
    PaTime defaultLowInputLatency; 
    PaTime defaultLowOutputLatency; 
    PaTime defaultHighInputLatency; 
    PaTime defaultHighOutputLatency; 
    double defaultSampleRate; 
} PaDeviceInfo; 
... 
const PaDeviceInfo* Pa_GetDeviceInfo(PaDeviceIndex device); 

程序使用从文档:

const PaDeviceInfo* Pa_GetDeviceInfo ( PaDeviceIndex device ) 

检索指针PaDeviceInfo结构其中包含有关指定的 设备的信息。

返回: 指向不可变PaDeviceInfo结构的指针。如果设备参数超出范围 ,该函数返回NULL。

参数: 设备有效的设备指数取值范围为0至(Pa_GetDeviceCount() - 1)


在VB程序我有:

Private Declare Function Pa_GetDeviceInfo Lib "portaudio_x86.dll" (ByVal dindex As Integer) As PaDeviceInfo 
... 
Private Structure PaDeviceInfo 
     Dim structVersion As Integer 
     <MarshalAs(Runtime.InteropServices.UnmanagedType.LPStr)> Dim name As String 
     Dim hostapi As Integer 
     Dim maxInputChannels As Integer 
     Dim maxOutputChannels As Integer 
     Dim defaultLowInputLatency As Double 
     Dim defaultLowOutputLatency As Double 
     Dim defaultHighInputLatency As Double 
     Dim defaultHighOutputLatency As Double 
     Dim defaultSampleRate As Double 
End Structure 
... 
     Dim di As New PaDeviceInfo 
     di = Pa_GetDeviceInfo(outputParameters.device) 

这种感觉错误作为文档状态Pa_GetDeviceInfo将指针返回到包含关于结构的信息 的结构,意味着函数最初创建结构。

我完全不熟悉混合语言编程,C++ utter noob和一个糟糕的VB程序员。 任何人都可以引导我以正确的方式来解决这个问题吗? 我的感觉是,我需要理解如何让VB引用在dll中创建的memry中的结构,所以我需要让vb将“指向东西的指针”理解为函数返回。

非常感谢您提供的任何帮助。请不要只是说rtfm,我在我的眼睛在FM的 分钟,我只是不知道在哪里看。

非常感谢, 大卫

+0

谁投了票,谢谢,但我希望有人有一个答案!说真的,我在'困难的东西'这个领域问的问题,因此不太可能得到答案,或者人们正在阅读这个问题,并且会“嘘嘘,什么是小白,回到麻烦的东西上”? – 2009-01-24 22:29:11

+0

看起来你正试图在VB.NET中处理互操作,所以我唯一的建议就是在C++/CLI中编写一些托管包装代码。从长远来看,这可能会让你的生活变得更轻松。另一方面,对于任何处理VB6或VBA互操作的人来说,我不能推荐本书的相关章节(现在可以在线获得)“Hardcore Visual Basic”:http://vb.mvps.org/铁杆/ – 2010-05-20 17:42:33

回答

3

你的API函数的声明是错误的。该函数返回一个不会反映在代码中的指针。签名转化为VB如下:

Private Declare Function Pa_GetDeviceInfo Lib "portaudio_x86.dll" (_ 
    ByVal dindex As Integer _ 
) As IntPtr 

当然,使用IntPtr直接是不容易的。事实上,颇有些编组是involved

Dim obj As PaDeviceInfo = _ 
    DirectCast(Marshal.PtrToStructure(ptr, GetType(PaDeviceInfo)), PaDeviceInfo) 

(或多或少是重要的)侧面说明:因为你的DLL显然是在内存中创建一个新的对象,它也需要释放/摧毁它。确保在使用该结构后调用相应的功能。

0

是的,你的结构是错误的。你必须得到一个指针,然后读取它“指向”的内存。

我以前在C++中完成了外部DLL调用,它通常涉及大量的文档浏览。我不认为这里有人会为你做这件事,但我会试着指出你的方向。

首先,一个指针是一个地址,一个“指向”内存中某个位置的值。 “取消引用”指针是读取指针指向的内存(如果您读取或写入错误的内存,内存可能会变得不安并杀死您的程序)。

此外,在低级别,调用DLL包括将信息的位复制到堆栈,然后让函数检索它们。 “调用惯例”完全描述了如何完成 - 有“c”,pascal和其他这样的惯例。

您将需要调用DLL的函数,获取指针,将指向的信息复制到本地结构中,然后继续。困难的事情将是搞清楚如何声明DLL函数。如果你的库文档有一些示例代码,那可能是从哪里开始的。

一个简短的Google甚至都没有显示任何一致的方式来处理VB中的指针。一个想法是创建一个简短的C++程序,它将调用DLL并通过值返回一个对象。我不知道这是否会有所帮助,但是在处理外部库时会出现这样的问题。

好运