如何解决从 vb.net 调用 dll 函数
我有一个名为 plclient_kompas.dll 的 CAD dll。这是一个标准机械制造零件库。
在plclient_kompas.dll中包含函数PLInsert3D,将标准零件从库中放入3D装配。
在这个库的手册中说:
HRESULT **PLInsert3D**(
[in] IPARTLibProvider* aPLClient;
[in] IBOResponseDisp* aMethodResponse;
[in] ksPlacement* aPlacement;
[out,retval] IDispatch** result);
所以我想从 vs2017 vb.net 代码中调用这个函数,如下所示:
<DllImport("C:\Program Files\ASCON\KOMPAS-3D v17\Libs\PARTLib\Clients\plclient_kompas.dll",CallingConvention:=CallingConvention.StdCall)>
Public Shared Function **PLInsert3D**(aPLClient As IPARTLibProvider,aMethodResponse As BOResponse,aPlacement As ksPlacement) As ksPart
End Function
Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
iMainPart = **PLInsert3D**(aPLClient,aMethodResponse,aPlacement)
End Sub
但在这一行:
iMainPart = **PLInsert3D**(aPLClient,aPlacement)
我有错误访问冲突异常。
我做错了什么?任何帮助将不胜感激。谢谢!
补充一下我写的。 这是我在 vb.net 中的代码:
Imports Kompas6API5
Imports KompasAPI7
Imports PARTLibClient
Imports BOSimple
Imports Kompas6Constants3D
Imports System.Runtime.InteropServices
Imports stdole
Public Class Form1
<DllImport("C:\Program Files\ASCON\KOMPAS-3D v17\Libs\PARTLib\Clients\plclient_kompas.dll",CallingConvention:=CallingConvention.StdCall)>
Public Shared Function PLInsert3D(ByRef aPLClient As IPARTLibProvider,ByRef aMethodResponse As BOResponse,ByRef aPlacement As ksPlacement) As <MarshalAs(UnmanagedType.Interface)> ksPart
End Function
Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
Dim kompas As Object
Dim ksdoc As Object
kompas = New Kompas6API5.Application
kompas.Visible = True
ksdoc = kompas.Document3D
ksdoc.Create(False,False)
ksdoc.Filename = "C:\Users\Baha1990\Documents\Visual Studio 2017\Projects\Kompas3D\3d files\1.a3d"
ksdoc.UpdateDocumentParam
ksdoc.Save
Dim aPLClient As BOSimpleProvider
aPLClient = New PARTLibClient.BOSimpleProvider
Dim Location As String
Dim Response As Object
Location = ""
Response = aPLClient.SelectEx(0,Location,0)
Dim aMethodResponse As BOResponse
aMethodResponse = aPLClient.GetMethod(Location,"КОМПАС 3D")
Dim iDoc3D As ksDocument3D
Dim iMainPart As ksPart
Dim aPlacement As ksPlacement
iDoc3D = kompas.ActiveDocument3D
iMainPart = iDoc3D.GetPart(-1)
aPlacement = iMainPart.GetPlacement
aPlacement.SetOrigin(0,0)
iMainPart = PLInsert3D(aPLClient,aPlacement)
End Sub
这是来自 C# API 手册的示例:
// Тестовая библиотека вставки объекта в КОМПАС из СИ
/*
* Необходимо у подключаемых библиотек BOSimple и PARTLibClient выставить значение параметра
* Embed Interop Types = False
*
* */
using System;
using Microsoft.Win32;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using KAPITypes;
using Kompas6Constants;
using Kompas6API5;
using Kompas6API7;
using PARTLibClient;
using BOSimple;
using Kompas6Constants3D;
using stdole;
using System.Runtime.Versioning;
namespace PartLibAPI
{
[ClassInterface(ClassInterfaceType.AutoDual)]
public class InsertKompas
{
const string _LIBRARYNAME = "Вставка изделия в Компас из СИ";
const string _KEYNAME = @"SOFTWARE\Classes\CLSID\{";
const string _KOMPASLIBRARY = "Kompas_Library";
const string _DLLPATH = "plclient_kompas.dll";
const string _KERNEL32 = "kernel32.dll";
#region Методы для работы библиотеки в Компас
private KompasObject _kompas;
// Название библиотеки
[return: MarshalAs(UnmanagedType.BStr)]
public string GetLibraryName()
{
return _LIBRARYNAME;
}
// Головная функция библиотеки
public void ExternalRunCommand([In] short command,[In] short mode,[In,MarshalAs(UnmanagedType.IDispatch)] object kompas_)
{
_kompas = (KompasObject)kompas_;
switch (command)
{
case 1:
InsertInKompas(_kompas);
break;
}
}
// Функция получения меню
// Описание функции можно найти в SDK API Компас
[return: MarshalAs(UnmanagedType.BStr)]
public string ExternalMenuItem(short number,ref short itemType,ref short command)
{
var result = string.Empty;
itemType = 1; // "MENUITEM"
switch (number)
{
case 1:
result = "Вставить";
command = 1;
break;
//
// Для корректной работы библиотеки необходимо добавить конец меню (или подменю)
//
case 2:
command = -1;
itemType = 3; // "ENDMENU"
break;
}
return result;
}
#endregion
// Делегаты для работы с методами из plclient_kompas.dll
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int _PLInsert2D(IPARTLibProvider aPLClient,IBOResponse aMethodResponse,double aX,double aY,double aAngle);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void _PLInsert3D([Out] out IDispatch retVal,IPARTLibProvider aPLClient,ksPlacement aPlacement);
private void InsertInKompas(KompasObject kompas)
{
// Подключаемся к plclient_kompas.dll (получаем ссылку на запущенный экземпляр в процессе Компаса)
IntPtr pDll = IntPtr.Zero;
try
{
pDll = LoadLibrary(_DLLPATH);
if (pDll == IntPtr.Zero)
throw new Exception("Не могу найти plclient_kompas.dll");
// Получаем адреса экспортируемых функций из ранее загруженной plclient_kompas.dll
var pProc2D = GetProcAddress(pDll,"PLInsert2D");
var pProc3D = GetProcAddress(pDll,"PLInsert3D");
// Получаем экземпляры делегатов,приведенных к соответствующему типу
var PLInsert2D = (_PLInsert2D)Marshal.GetDelegateForFunctionPointer(pProc2D,typeof(_PLInsert2D));
var PLInsert3D = (_PLInsert3D)Marshal.GetDelegateForFunctionPointer(pProc3D,typeof(_PLInsert3D));
IApplication kompasApp = kompas.ksGetApplication7();
if (kompasApp == null)
throw new Exception("Не удалось получить указатель на интерфейс приложения!");
var doc2D = (Document2D)kompas.ActiveDocument2D();
var doc3D = (Document3D)kompas.ActiveDocument3D();
if ((doc2D == null) && (doc3D == null))
throw new Exception("Откройте документ или создайте новый!");
// Подключаемся к API справочника
IPARTLibProvider PLClient = null;
try
{
PLClient = new BOSimpleProvider();
var errorMsg = String.Empty;
// Подключаемся к серверу приложений
if (PLClient.Connect(ref errorMsg) == 0)
{
try
{
// Получаем доступ к изделиям и папкам в справочнике
var commonData = PLClient.CreateCommonDataObj();
commonData.InitUserData();
string plm2D = "2D"; // Документ 2D
string plm3D = "Solid3D"; // Документ 3D
// Типы документов Компаса
string[] methodNames = { "","КОМПАС 2D","КОМПАС 3D","" };
string[] docName = { "?",plm2D,plm3D,"?" };
// Получаем тип документа
var docType = GetDocType(kompasApp);
ksPart mainPart = null;
ksPart pPart = null;
ksPlacement partPlace = null;
if (docType == DocumentTypeEnum.ksDocumentAssembly)
{
if (doc3D != null)
{
mainPart = doc3D.GetPart((short)Part_Type.pTop_Part);
if (mainPart != null)
{
pPart = doc3D.GetPart(0);
partPlace = pPart != null ? pPart.GetPlacement() : mainPart.GetPlacement();
}
}
}
// Задаем режим работы справочника в зависимости от типа активного документа в КОМПАС
commonData.SetFindOptions(docName[(int)docType]);
// Путь до корневого каталога с ISO стандартами по уникальному ID
var ISOFolder = commonData.FolderByID("A259_151417DFF6474BF6");
// Просматриваем каталог в глубину
while (ISOFolder.FolderCollection().Count() > 0)
{
ISOFolder = ISOFolder.FolderCollection().Folder(0);
// В случае если в каталоге есть хотя бы один класс
if (ISOFolder.ClassCollection().Count() > 0)
{
// Получаем указатель на интерфейс первой типоразмерной таблицы его изделий
var ISOClass = ISOFolder.ClassCollection().plClass(0);
var instance = ISOClass.Instances("",docName[(int)docType]);
var paramGrid = instance.ParamGrid(0);
// Просматриваем типоразмерную таблицу сверху-вниз
for (int i = 0; i < paramGrid.PGRowCount(); i++)
{
// Выбираем строку
paramGrid.SelectRow(i);
// Получаем полный location получившегося изделия
var location = instance.plPart().GetLocation(0);
// Получаем метод для вставки изделия в зависимости от типа активного документа
var methodResponce = PLClient.GetMethod(location,methodNames[(int)docType]);
// Вставляем изделие в КОМПАС
var X = 5 * i * Math.Sin(15 * Math.PI * i / 180);
var Y = 5 * i * Math.Cos(15 * Math.PI * i / 180);
var Angle = 180 - i * 15;
IDispatch kPart;
switch (docType)
{
case DocumentTypeEnum.ksDocumentAssembly:
// Задаем место в сборке
partPlace.SetOrigin(X,Y,0);
PLInsert3D(out kPart,PLClient,methodResponce,partPlace);
break;
case DocumentTypeEnum.ksDocumentDrawing:
PLInsert2D(PLClient,X,Angle);
break;
case DocumentTypeEnum.ksDocumentFragment:
PLInsert2D(PLClient,Angle);
break;
case DocumentTypeEnum.ksDocumentSpecification:
PLInsert3D(out kPart,null);
break;
}
}
}
}
}
catch (Exception ex)
{
kompas.ksMessage(ex.Message);
}
finally
{
// Отключаемся от сервера приложений
PLClient.Disconnect();
}
}
else
kompas.ksMessage("Ошибка подключения к серверу приложений: " + errorMsg);
}
catch (Exception ex)
{
kompas.ksMessage("Ошибка! Не удалось создать COM-объект." + ex.Message);
}
}
catch (Exception ex)
{
kompas.ksMessage(ex.Message);
}
finally
{
// Освобождаем загруженную plclient_kompas.dll
FreeLibrary(pDll);
}
}
/// <summary>
/// Метод определения типа документа
/// </summary>
/// <param name="kompasApp"></param>
/// <returns></returns>
private DocumentTypeEnum GetDocType(IApplication kompasApp)
{
return kompasApp.ActiveDocument == null ? DocumentTypeEnum.ksDocumentUnknown : kompasApp.ActiveDocument.DocumentType;
}
// Импортируем в проект методы из kernel32.dll для подключения к plclient_kompas.dll
[DllImport(_KERNEL32,CharSet = CharSet.Unicode,SetLastError = true)]
[ResourceExposure(ResourceScope.Process)]
public static extern IntPtr LoadLibrary(string libFilename);
[DllImport(_KERNEL32,CharSet = CharSet.Ansi,BestFitMapping = false,ThrowOnUnmappableChar = true)]
static internal extern IntPtr GetProcAddress(IntPtr HModule,[MarshalAs(UnmanagedType.LPStr),In] string funcName/*lpcstr*/);
[DllImport(_KERNEL32,SetLastError = true)]
[ResourceExposure(ResourceScope.Process)]
public static extern bool FreeLibrary(IntPtr hModule);
#region COM Registration
// Эта функция выполняется при регистрации класса для COM
// Она добавляет в ветку реестра компонента раздел Kompas_Library,// который сигнализирует о том,что класс является приложением Компас,// а также заменяет имя InprocServer32 на полное,с указанием пути.
// Все это делается для того,чтобы иметь возможность подключить
// библиотеку на вкладке ActiveX.
[ComRegisterFunction]
public static void RegisterKompasLib(Type t)
{
RegistryKey regKey = Registry.LocalMachine;
try
{
var keyName = string.Format("{0}{1}{2}",_KEYNAME,t.GUID.ToString(),"}");
regKey = regKey.OpenSubKey(keyName,true);
regKey.CreateSubKey(_KOMPASLIBRARY);
regKey = regKey.OpenSubKey("InprocServer32",true);
regKey.SetValue(null,System.Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\mscoree.dll");
}
catch (Exception ex)
{
MessageBox.Show(string.Format("При регистрации класса для COM-Interop произошла ошибка:\n{0}",ex));
}
finally
{
regKey.Close();
}
}
// Эта функция удаляет раздел Kompas_Library из реестра
[ComUnregisterFunction]
public static void UnregisterKompasLib(Type t)
{
RegistryKey regKey = Registry.LocalMachine;
var keyName = string.Format("{0}{1}{2}","}");
RegistryKey subKey = regKey.OpenSubKey(keyName,true);
try
{
subKey.DeleteSubKey(_KOMPASLIBRARY);
}
finally { subKey.Close(); }
}
#endregion
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。