Author Topic: NET P/INVOKE Routines  (Read 31011 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
NET P/INVOKE Routines
« on: January 27, 2010, 06:49:43 PM »
LIBRARY THREAD for  AutoCAD P/INVOKE
 Members are encouraged to post any functions, methods, snips regarding
AutoCAD P/INVOKE in .NET : C# ,  VB , F# , Python , etc

Feel free to include comments, descriptive notes, limitations,  and images to document your post.

Please post questions in a regular thread.


added Note:
Be aware that the p/invoke methods sometimes have :
different entry points in different ACAD Versions due to name mangling
and
different entry point signatures dependant on x32 or x64 platforms.
« Last Edit: January 29, 2010, 05:45:35 PM by Kerry Brown »
kdub in one timeline.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<-

MickD

  • King Gator
  • Posts: 3520
  • (x-in)->[process]->(y-out)
Re: NET P/INVOKE Routines
« Reply #1 on: January 27, 2010, 07:40:27 PM »
Here's a few to kick off with, some or all may be obselete now but they may be of use just for reference.

Code: [Select]

        [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl,
             EntryPoint = "?acedSetCurrentView@@YA?AW4ErrorStatus@Acad@@PAVAcDbViewTableRecord@@PAVAcDbViewport@@@Z")]
        private static extern int acedSetCurrentView(IntPtr pVtr, /*IntPtr.Zero*/IntPtr pVP);

        [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedTrans")]
        static extern int acedTrans(double[] point, IntPtr fromRb, IntPtr toRb, int disp, double[] result);

        [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl,
             EntryPoint = "?acedVports2VportTableRecords@@YA?AW4ErrorStatus@Acad@@XZ")]
        private static extern bool acedVports2VportTableRecords();

        [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl,
             EntryPoint = "?acedVportTableRecords2Vports@@YA?AW4ErrorStatus@Acad@@XZ")]
        private static extern bool acedVportTableRecords2Vports();
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

"The E in Javascript stands for 'easy'." Florin Pop tweet

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8403
  • AKA Daniel
Re: NET P/INVOKE Routines
« Reply #2 on: January 27, 2010, 08:50:15 PM »
Since p/invoke methods sometimes have different entry points due to name mangling, maybe it would be a good idea to specify the Acad version.

fixo

  • Guest
Re: NET P/INVOKE Routines
« Reply #3 on: January 28, 2010, 04:06:56 AM »
Since p/invoke methods sometimes have different entry points due to name mangling, maybe it would be a good idea to specify the Acad version.
Would be interesting to see the example of usage as well...:)

~J'~

LE3

  • Guest
Re: NET P/INVOKE Routines
« Reply #4 on: April 13, 2010, 12:52:43 PM »
Just by any chance...
Anyone have done a PInvoke for std:map ?

Like from unmanaged:
Code: [Select]
extern "C" __declspec(dllexport)
void steelMEPcollisions (map<AcDbObjectId, double> pipeDiamMap) { ... }

I wish the above could be to easy like to managed:
Code: [Select]
[DllImport(STEEL_ARX, CallingConvention = CallingConvention.Cdecl, EntryPoint = "steelMEPcollisions ")]
public static extern void CollisionsSteelMEP ( Dictionary<ObjectId, Double> pipeDiamMap );

Thanks.
« Last Edit: August 13, 2010, 02:34:03 PM by LE »

LE3

  • Guest
Re: NET P/INVOKE Routines
« Reply #5 on: April 13, 2010, 01:50:03 PM »
On the mean time, will go into this route:
> To use separate arguments for the ids and the doubles and make sure to keep the same location in their AcArray's - have done some with these types, so guess will be much easier.
 
Like from unmanaged:
Code: [Select]
extern "C" __declspec(dllexport)
void steelMEPcollisions (map<AcDbObjectId, double> pipeDiamMap) { ... }

I which the above could be to easy like to managed:
Code: [Select]
[DllImport(STEEL_ARX, CallingConvention = CallingConvention.Cdecl, EntryPoint = "steelMEPcollisions ")]
public static extern void CollisionsSteelMEP ( Dictionary<ObjectId, Double> pipeDiamMap );

LE3

  • Guest
Re: NET P/INVOKE Routines
« Reply #6 on: April 13, 2010, 08:45:18 PM »
In case someone end up smashing on the same wall:

The ticket (or the easier route for me) was to use resbuf* and ResultBuffer

Code: [Select]
// C++ - unmanaged
extern "C" __declspec(dllexport)
void steelMEPcollisions ( resbuf *pArgs ) { ... }

// C# - managed    
public static class SteelFunctions        
{
    [DllImport(STEEL_ARX, CallingConvention = CallingConvention.Cdecl, EntryPoint = "steelMEPcollisions ")]
    public static extern void CollisionsSteelMEP ( IntPtr pArgs );
}
        
public static void CollisionsMEPSteel ( ResultBuffer args )    
{        
    SteelFunction.CollisionsSteelMEP( args.UnmanagedObject );        
}

ResultBuffer args = new ResultBuffer();                        
args.Add(new TypedValue((int)LispDataType.ListBegin, -1));                        
args.Add(new TypedValue((int)LispDataType.ListBegin, -1));                        
args.Add(new TypedValue((int)LispDataType.Int32, oldIdPtr.ToInt32()));                        
args.Add(new TypedValue((int)LispDataType.Double, diam));                      
args.Add(new TypedValue((int)LispDataType.ListEnd, -1));                        
args.Add(new TypedValue((int)LispDataType.ListEnd, -1));

PInvoke.CollisionsMEPSteel(args);
« Last Edit: April 14, 2010, 10:37:52 AM by LE3 »

jgr

  • Guest
Re: NET P/INVOKE Routines
« Reply #7 on: May 25, 2010, 08:16:17 PM »
FindText "API", with acad 2007 32-bit

Code: [Select]
'#define AC_SRCH_BLOCK         0x01
'#define AC_SRCH_DIM_TEXT      0x02
'#define AC_SRCH_TEXT          0x04
'#define AC_SRCH_LINK_DESC     0x08
'#define AC_SRCH_LINK_URL      0x10
'#define AC_SRCH_MATCH_CASE    0x20
'#define AC_SRCH_WHOLE_WORD    0x40

'#define AC_SRCH_DEFAULT       0x1F

'bool acdbTextFind(AcDbDatabase* pDatabase,
'                  AcDbObjectIdArray& resultSet,
'                  const ACHAR* findString,
'                  const ACHAR* replaceString = NULL,
'                  Adesk::UInt8 searchOptions = AC_SRCH_DEFAULT,
'                  const AcDbObjectIdArray& selSet = 0);

Public Const AC_SRCH_BLOCK As Integer = 1

Public Const AC_SRCH_DIM_TEXT As Integer = 2

Public Const AC_SRCH_TEXT As Integer = 4

Public Const AC_SRCH_LINK_DESC As Integer = 8

Public Const AC_SRCH_LINK_URL As Integer = 16

Public Const AC_SRCH_MATCH_CASE As Integer = 32

Public Const AC_SRCH_WHOLE_WORD As Integer = 64

Public Const AC_SRCH_DEFAULT As Integer = 31


<DllImport("acdb17.dll", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Unicode, EntryPoint:="?acdbTextFind@@YA_NPAVAcDbDatabase@@AAV?$AcArray@VAcDbObjectId@@V?$AcArrayMemCopyReallocator@VAcDbObjectId@@@@@@PB_W2EABV2@@Z")> _
Private Shared Function acdbTextFind(ByVal pDb As System.IntPtr, _
                                 ByVal resultSet As System.IntPtr, _
                           <System.Runtime.InteropServices.InAttribute(), System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal findString As String, _
                           <System.Runtime.InteropServices.InAttribute(), System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal replaceString As String, _
                           ByVal searchOptions As Integer, _
                           ByVal selSet As System.IntPtr) As <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.I1)> Boolean
End Function



Public Shared Sub ZZ()

    Dim oidIn As New ObjectIdCollection
    Dim oidOut As New ObjectIdCollection
    Dim ret As Boolean

    Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database

    ret = acdbTextFind(db.UnmanagedObject, oidOut.UnmanagedObject, "hello", Nothing, AC_SRCH_DEFAULT, oidIn.UnmanagedObject)

    If ret Then
        For Each id As ObjectId In oidOut
            '
        Next
    End If

    oidIn.Dispose()
    oidOut.Dispose()
End Sub


can someone explain to me why different entry point signatures dependant on x32 or x64 platforms? i read this in first post, and i do not understand (I come from vba/vb6)
« Last Edit: May 25, 2010, 08:24:59 PM by jgr »

Peter Jamtgaard

  • Guest
Re: NET P/INVOKE Routines
« Reply #8 on: May 28, 2010, 05:41:38 PM »
I have been playing with this for using lisp.

Code: [Select]

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices
Imports System.Runtime.InteropServices 'for DllImport()
Imports System.Security

<System.Security.SuppressUnmanagedCodeSecurity(), DllImport("acad.exe", CallingConvention:=CallingConvention.Cdecl)> _
    Private Shared Function acedInvoke(ByVal rbIn As IntPtr, <Out()> ByRef rbOut As IntPtr) As Integer
    End Function
    Public Shared Function InvokeLisp(ByVal resbuf As ResultBuffer) As ResultBuffer
        Dim rb As IntPtr = IntPtr.Zero
        Class1.acedInvoke(resbuf.UnmanagedObject, rb)
        Return DirectCast(DisposableWrapper.Create(GetType(ResultBuffer), rb, True), ResultBuffer)
    End Function

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: NET P/INVOKE Routines
« Reply #9 on: May 28, 2010, 06:27:58 PM »

Peter,

Isn't that the code gile posted for you elsewhere ??

Regards,

kdub in one timeline.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<-

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8403
  • AKA Daniel
Re: NET P/INVOKE Routines
« Reply #10 on: May 28, 2010, 08:44:43 PM »

Peter,

Isn't that the code gile posted for you elsewhere ??

Regards,



looks like a vb version of  http://www.theswamp.org/index.php?topic=33352.msg387539#msg387539 ?

gile

  • Water Moccasin
  • Posts: 2457
  • Marseille, France
Re: NET P/INVOKE Routines
« Reply #11 on: May 29, 2010, 03:39:43 AM »
Hi,

The code I posted "elsewhere" was greatly inspired by Daniel's and Tony's (here) ones.
Speaking English as a French Frog

Peter Jamtgaard

  • Guest
Re: NET P/INVOKE Routines
« Reply #12 on: May 29, 2010, 08:37:08 AM »

Peter,

Isn't that the code gile posted for you elsewhere ??

Regards,



Yes, I just thought I would add it here, for discussion.

LE3

  • Guest
Re: NET P/INVOKE Routines
« Reply #13 on: August 13, 2010, 02:25:34 PM »
Here is one, I just found out:
Code: [Select]
[DllImport("acad.exe")]
public static extern void acedPostCommandPrompt ( );

Just place this at the end of your function: acedPostCommandPrompt(); and will do the trick.

Have been fighting on re-display the Command: line prompt after calling/executing a function from a modeless form.
i.e:
Command:
Table position:

And after finished with the function, and going back to the form (focus) you will still see in the command line:
Table position:

Until you go to the drawing screen area and do a click with your mouse, for example, and that will bring back the prompt:
Command:

Jeff H

  • Needs a day job
  • Posts: 6131
Re: NET P/INVOKE Routines
« Reply #14 on: August 13, 2010, 05:04:29 PM »
2011 preview icon for blocks if misssing

<DllImport("acad.exe", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Unicode)> _
   Private Shared Function acedCommand(ByVal type1 As Integer, ByVal command As String, ByVal type2 As Integer, ByVal blockName As String, ByVal [end] As Integer) As Integer

End Function
 acedCommand(5005, "BLOCKICON", 5005, blkName, 5000)