none
wpf c# 2010调用vc dll字符串问题 RRS feed

  • 问题

  • 大家好,我使用wpf c# 2010 调用vc2010非托管代码写的dll时遇到一个奇怪问题。

    vc代码:

    extern	"C"
    {
        DLL_DECL_SPEC   int __stdcall	 GetReport(int id,LPSTR retPath);
    }
    
    int __stdcall	GetReport(int id,LPSTR retPath)
    {
            strcpy_s(retPath,1,"");
            return -1;
    }
    

    c#调用代码:

     

    class runManiDll
    {
    public string GetReport(int id) 
        {
            StringBuilder ret = new StringBuilder(256);
    
            dllMain.GetReport(id, ret);
            return ret.ToString();
        }
    }
    
        public partial class dllMain
        {
    
                [System.Runtime.InteropServices.DllImportAttribute("VcMainDll.dll", EntryPoint = "GetReport", CallingConvention = CallingConvention.StdCall ,CharSet=CharSet.Ansi)]
            public unsafe static extern int GetReport(int id, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]  System.Text.StringBuilder retPath);
    }
    
    运行时出错误提示:
    “System.AccessViolationException”类型的未经处理的异常出现在 WindowsBase.dll 中。

     

    其他信息: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

    一开始使用的是Cdecl,遇到这个错误,改成StdCall仍然是这个错误。加上unsafe 还是这个错误。但如果我使用一个struct,其中有一项是string,则能正确返回我要的字符串,不出错。请问问题在哪,怎么解决?

     


    • 已编辑 tobzk 2011年11月8日 7:40
    • 已移动 Dummy yoyo 2011年11月11日 7:19 (发件人:Visual C#)
    2011年11月8日 7:38

答案

  • Hi tobzk,

    欢迎来到MSDN论坛!

    我将把该帖子移到C++论坛以便能够得到更好的支持。

     

    同时,下面是我在本地建的项目,供您参考:

    1. C++ 部分:

    // TestDll.cpp : Defines the exported functions for the DLL application.
    //
    
    #include "stdafx.h"
    
    extern "C" __declspec(dllexport) int GetReport(int id, char* retPath) 
    { 
    	strcpy_s(retPath,1,""); 
    	return -1; 
    }
    
    

    2. C# 部分, Console项目。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {      
            [DllImportAttribute("TestDll.dll", EntryPoint = "GetReport", 
                CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
            public unsafe static extern int GetReport(int id, 
                [MarshalAsAttribute(UnmanagedType.LPStr)]  System.Text.StringBuilder retPath);
            static void Main(string[] args)
            {
                int x = Program.GetReport(3, new StringBuilder("askask"));
                Console.WriteLine(x.ToString());
            }
        }
    }
    

    运行C#项目后,得到正确的返回值 -1.

    建议您在本地运行下我提供的代码。请您确保是在“管理员权限”下运行程序。 

    谢谢您的理解!


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 Helen Zhao 2011年11月16日 3:38
    2011年11月11日 7:18
  • 你好,

    我想可能是你的DLL没有成功导出GetReport函数。

    下面是我的步骤和一些代码,希望对你有所帮助。

    1-】DLL项目的test.h头文件添加代码:

    extern	"C"
    {
       _declspec(dllexport)  int __stdcall	 GetReport(int id,LPSTR retPath);
    }
    

    2-】DLL项目的.cpp文件添加代码:

    #include "test.h"
    int __stdcall	GetReport(int id,LPSTR retPath)
    {
        strcpy_s(retPath,1,"");
        return -1;
    }
    
    


    3-】然后把生成的.dll拷到C#项目的debug/bin目录下。

    4-】类dllMain的代码(去掉了unsafe关键字):

     public partial class dllMain
        {
            [System.Runtime.InteropServices.DllImportAttribute("dd.dll", EntryPoint = "GetReport", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
            public static extern int GetReport(int id, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]  System.Text.StringBuilder retPath);
        }
    

    5-】在Main函数中的代码:

    static void Main(string[] args)
            {
                StringBuilder ret = new StringBuilder(256);
                dllMain.GetReport(3, ret);          
                Console.WriteLine(ret.ToString());           
            }
    

    6-】运行C#程序,没有遇到错误和警告。

    希望我的回复对你有所帮助。

    谢谢!
     


    Helen Zhao[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    • 已编辑 Helen Zhao 2011年11月11日 9:15
    • 已建议为答案 Helen Zhao 2011年11月14日 8:25
    • 已标记为答案 Helen Zhao 2011年11月16日 3:38
    2011年11月11日 9:13
  • 谢谢您的回复,问题已经解决,工程比较大,里边有很多vc和c#的项目,可能是来回改之后,没有重新编译的问题,我的代码当时在工程内有问题,单独新建一个工程运行也能正确,后来整个工程所有的vc和c#项目全部都clean一遍,重新编译后就没问题了。
    • 已标记为答案 Helen Zhao 2011年11月17日 8:22
    2011年11月17日 6:40

全部回复

  • 把 Charset 改成 Auto 试试看。不确定 LPSTR 的 DLL 是否启用了 Unicode。LPSTR 不一定是 ANSI 的。
    Mark Zhou
    2011年11月8日 9:33
  • Hi tobzk,

    欢迎来到MSDN论坛!

    我将把该帖子移到C++论坛以便能够得到更好的支持。

     

    同时,下面是我在本地建的项目,供您参考:

    1. C++ 部分:

    // TestDll.cpp : Defines the exported functions for the DLL application.
    //
    
    #include "stdafx.h"
    
    extern "C" __declspec(dllexport) int GetReport(int id, char* retPath) 
    { 
    	strcpy_s(retPath,1,""); 
    	return -1; 
    }
    
    

    2. C# 部分, Console项目。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {      
            [DllImportAttribute("TestDll.dll", EntryPoint = "GetReport", 
                CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
            public unsafe static extern int GetReport(int id, 
                [MarshalAsAttribute(UnmanagedType.LPStr)]  System.Text.StringBuilder retPath);
            static void Main(string[] args)
            {
                int x = Program.GetReport(3, new StringBuilder("askask"));
                Console.WriteLine(x.ToString());
            }
        }
    }
    

    运行C#项目后,得到正确的返回值 -1.

    建议您在本地运行下我提供的代码。请您确保是在“管理员权限”下运行程序。 

    谢谢您的理解!


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 Helen Zhao 2011年11月16日 3:38
    2011年11月11日 7:18
  • 你好,

    我想可能是你的DLL没有成功导出GetReport函数。

    下面是我的步骤和一些代码,希望对你有所帮助。

    1-】DLL项目的test.h头文件添加代码:

    extern	"C"
    {
       _declspec(dllexport)  int __stdcall	 GetReport(int id,LPSTR retPath);
    }
    

    2-】DLL项目的.cpp文件添加代码:

    #include "test.h"
    int __stdcall	GetReport(int id,LPSTR retPath)
    {
        strcpy_s(retPath,1,"");
        return -1;
    }
    
    


    3-】然后把生成的.dll拷到C#项目的debug/bin目录下。

    4-】类dllMain的代码(去掉了unsafe关键字):

     public partial class dllMain
        {
            [System.Runtime.InteropServices.DllImportAttribute("dd.dll", EntryPoint = "GetReport", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
            public static extern int GetReport(int id, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]  System.Text.StringBuilder retPath);
        }
    

    5-】在Main函数中的代码:

    static void Main(string[] args)
            {
                StringBuilder ret = new StringBuilder(256);
                dllMain.GetReport(3, ret);          
                Console.WriteLine(ret.ToString());           
            }
    

    6-】运行C#程序,没有遇到错误和警告。

    希望我的回复对你有所帮助。

    谢谢!
     


    Helen Zhao[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    • 已编辑 Helen Zhao 2011年11月11日 9:15
    • 已建议为答案 Helen Zhao 2011年11月14日 8:25
    • 已标记为答案 Helen Zhao 2011年11月16日 3:38
    2011年11月11日 9:13
  • 谢谢您的回复,问题已经解决,工程比较大,里边有很多vc和c#的项目,可能是来回改之后,没有重新编译的问题,我的代码当时在工程内有问题,单独新建一个工程运行也能正确,后来整个工程所有的vc和c#项目全部都clean一遍,重新编译后就没问题了。
    • 已标记为答案 Helen Zhao 2011年11月17日 8:22
    2011年11月17日 6:40