在MFC编写的DLL名为ABC.dll中,一个函数定义如下:
typedef void *ABCHANDLE;
__declspec(dllexport) int __stdcall ABC_Init(ABCHANDLE *hHandle);我现在想在我的C#程序中调用这个函数,我的做法是:
[DllImport("ABC.dll", EntryPoint = "ABC_Init“)]
public static extern int ABC_Init(IntPtr pHandle);
private void B1_Click(object sender, EventArgs e)
{
    IntPtr handle = new IntPtr();
    ABC_Init(handle);
}当调用Init时,总是有运行时错误:
无法加载 DLL ”ABC.dll“:内存分配访问失效。(异常来自HRESULT:0x800703E6)各位高手帮忙解决啦~~~

解决方案 »

  1.   

    改为传递引用也不行:
    [DllImport("ABC.dll", EntryPoint = "ABC_Init“)] 
    public static extern int ABC_Init(ref IntPtr pHandle); 
    private void B1_Click(object sender, EventArgs e) 

        IntPtr handle = new IntPtr(); 
        ABC_Init(ref handle); 
    } 改为输出也不行,事实上的确是在函数内部给pHandle赋值的:
    [DllImport("ABC.dll", EntryPoint = "ABC_Init“)] 
    public static extern int ABC_Init(out IntPtr pHandle); 
    private void B1_Click(object sender, EventArgs e) 

        IntPtr handle;
        ABC_Init(out handle); 

      

  2.   

    1、你能看到c++ 的代码吗 ,能得话调试一下
    2、new IntPtr 不行 
    try
    IntPtr handler = Marshal.AllocHGlobal(size);
    传入
      

  3.   

    to hdt
    1,看不到源码,只有接口文件;
    2,size 指的什么? 我试过 32 、64 都不行,同样错误;
    谢谢!
      

  4.   

    C++ 同一语句,在不同的语境 作用完全不同,最好能有代码,或者C++ 这个DLL 的调用方式
      

  5.   

    你可以用C++调用一下这个dll试试,要保证你的这个dll可用
      

  6.   

    C++版的调用早就写好了,我现在就是做C++到C#的改版呢
      

  7.   


    [DllImport("ABC.dll", EntryPoint = "ABC_Init“)]  
    public static extern int ABC_Init(ref IntPtr pHandle);  
    private void B1_Click(object sender, EventArgs e)  
    {  
        IntPtr handle;  
        ABC_Init(ref handle);  
    }  估计这样应该可以.
      

  8.   

    10楼的做法我在3楼就说过不行的C++中的调用:
    在StdAfx.cpp中加入如下代码,#pragma message("Automatically linking with KCBPCli.lib")
    #pragma comment(lib,"KCBPCli.lib")并在***Dlg.h中加入头文件:#include "KCBPCli.h"之后就可以在C***Dlg类中调用诸如
    ABC.Init(ABCHANDLE *pHandle);
    等函数了。
      

  9.   

    用 ref 的话必须赋初值的
      

  10.   

    dll 是输出c样式的函数还是c++ 的类成员函数,如果是类成员函数 C#无法直接调用,你需要用c 再包装一次
      

  11.   

    不是太明白,能不能说的跟详细一点。ABCCli.h 是这样的:
    #ifndef _ABCCLI_H
    #define _ABCCLI_H#include <time.h>#ifdef WIN32
    #ifdef ABCCLI_EXPORTS
    #define ABCCLI_API __declspec(dllexport)
    #else
    #define ABCCLI_API __declspec(dllimport)
    #endif
    #define ABCCLISTDCALL __stdcall /* ensure stcall calling convention on NT */
    #else
    #define ABCCLI_API
    #define ABCCLISTDCALL /* leave blank for other systems */
    #endif/* Transact option values  */
    #define ABC_COMMIT 9
    #define ABC_ROLLBACK 10
    。#if (defined(ABC_AIX) && defined(__xlC__))
    #pragma options align = packed
    #else
    #pragma pack(1)
    #endif
    typedef struct
    {
        .........
    }
    tagABCConnectOption;#define ABC_PROXY_MAX 128
    #define ABC_SSL_MAX 256
    typedef struct
    {
        。
    }
    tagABCConnectOptionEx;/* callback notification function definition. */
    typedef void (ABCCLI_Callback_t) (void *);
    typedef ABCCLI_Callback_t *ABCCLI_Notify_t;/* control parameters to publish/subscribe queue primitives */
    typedef struct
    {
        。
    } tagCallCtrl;typedef tagCallCtrl tagABCPSControl;#if (defined(ABC_AIX) && defined(__xlC__))
    #pragma options align = reset
    #elif defined(ABC_SOL)
    #pragma pack(4)
    #else
    #pragma pack()
    #endif
    typedef void* ABCCLIHANDLE;#ifdef __cplusplus
    extern "C"
    {
    #endif
    ABCCLI_API int ABCCLISTDCALL ABCCLI_Init(ABCCLIHANDLE *hHandle);
    ABCCLI_API int ABCCLISTDCALL ABCCLI_Exit(ABCCLIHANDLE hHandle);
    。。


      

  12.   

    用depends.exe 看看这个dll到底输出函数名是什么
      

  13.   

    depends.exe  没用过呢。。呵呵 
    请问怎么用啊?
      

  14.   

    这样封装了一下,但是还是不行一样的错误!#include "stdafx.h"
    #include "ABCCli.h"BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
     )
    {
        return TRUE;
    }// 导出函数,使用“ _stdcall ” 标准调用extern "C" _declspec(dllexport) int _stdcall count(int init);
    int _stdcall count(int init)
    {
    static int S=init;
    S++;
    return S;
    }extern "C" _declspec(dllexport) int _stdcall ABCCLI_InitCS(ABCCLIHANDLE *pHandle);
    int _stdcall ABCCLI_InitCS(ABCCLIHANDLE *pHandle)
    {
    ABCCLIHANDLE handle;
    return ABCCLI_Init(&handle);
    }
    在C#中的调用方式和上面相同。但是同一个dll中的另外一个函数 count 确调用正常有点莫名其妙,,,
      

  15.   

    刚用depend 看过,
    这个DLL,导出的函数名前半部分是C++的,例如:
    CABCCli::CABCCli(void)
    CABCCli::~CABCCli(void)
    ....后半部分,应该是C形式的吧:
    ABCCLI_Init
    ABCCLI_Exit
    .....
      

  16.   

    extern "C" 有这个东西就说明是C形式的
    否则VC就会用C++的编译器去编译它,自动生成输出函数,得到你不想要的东西
    所以你想要输出函数,就需要extern "C"这个东西
      

  17.   

    15.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?首先,作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数extern "C"是连接申明(linkage declaration),被extern "C"修饰的变量和函数是按照C语言方式编译和连接的,来看看C++中对类似C的函数是怎样编译的:作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为: void foo( int x, int y );
      该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。未加extern "C"声明时的连接方式假设在C++中,模块A的头文件如下:// 模块A头文件 moduleA.h
    #ifndef MODULE_A_H
    #define MODULE_A_H
    int foo( int x, int y );
    #endif  在模块B中引用该函数:// 模块B实现文件 moduleB.cpp
    #i nclude "moduleA.h"
    foo(2,3);
      实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!加extern "C"声明后的编译和连接方式加extern "C"声明后,模块A的头文件变为:// 模块A头文件 moduleA.h
    #ifndef MODULE_A_H
    #define MODULE_A_H
    extern "C" int foo( int x, int y );
    #endif  在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:
    (1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;(2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):实现C++与C及其它语言的混合编程。  明白了C++中extern "C"的设立动机,我们下面来具体分析extern "C"通常的使用技巧:extern "C"的惯用法(1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:extern "C"
    {
    #i nclude "cExample.h"
    }而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。C++引用C函数例子工程中包含的三个文件的源代码如下:/* c语言头文件:cExample.h */
    #ifndef C_EXAMPLE_H
    #define C_EXAMPLE_H
    extern int add(int x,int y);
    #endif
    /* c语言实现文件:cExample.c */
    #i nclude "cExample.h"
    int add( int x, int y )
    {
    return x + y;
    }
    // c++实现文件,调用add:cppFile.cpp
    extern "C" 
    {
    #i nclude "cExample.h"
    }
    int main(int argc, char* argv[])
    {
    add(2,3); 
    return 0;
    }如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C" { }。
    (2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。C引用C++函数例子工程中包含的三个文件的源代码如下://C++头文件 cppExample.h
    #ifndef CPP_EXAMPLE_H
    #define CPP_EXAMPLE_H
    extern "C" int add( int x, int y );
    #endif
    //C++实现文件 cppExample.cpp
    #i nclude "cppExample.h"
    int add( int x, int y )
    {
    return x + y;
    }
    /* C实现文件 cFile.c
    /* 这样会编译出错:#i nclude "cExample.h" */
    extern int add( int x, int y );
    int main( int argc, char* argv[] )
    {
    add( 2, 3 ); 
    return 0;
    }
      

  18.   

    以前我调用delphi写的dll控件也如此。我当时是因为传入函数的数据类型问题,但是我最终也没能解决那个问题,或者你可以再用c+把这个dll打包成com?
      

  19.   

    delphi顺序是不一样的。所以一定得要改。
    ABC_Init里的代码报的错。所以楼主一定要贴里面的代码了。或者告知里面是如何使用ABCHANDLE ,
    ABCHANDLE 是一个函数指针。在c#里为委托。你传一个inptr.zero肯定不行了。