Can I link class/record methods to an external module?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















In Delphi I can link to external code like so:



   {$L 'C:UsersJohanDocumentsEmbarcaderoStudioProjectsLife64Lazaruslibx86_64-win64AVXGenerate.o'}

function GenerateQtoP_AVX_32(main, N,W,NW: pointer): byte;
external name 'AVXGENERATE_$$_GENERATEQTOP_AVX_32$POINTER$POINTER$POINTER$POINTER$$BYTE';
function GeneratePtoQ_AVX_32(main, S,E,SE: pointer): byte;
external name 'AVXGENERATE_$$_GENERATEPTOQ_AVX_32$POINTER$POINTER$POINTER$POINTER$$BYTE';
procedure ReverseBitsInAllBytes(ReverseMe: pointer);
external name 'AVXGENERATE_$$_REVERSEBITSINALLBYTES$POINTER';


In this case it links to AVX2 assembly code I write in Lazarus.



Is there a way to link member methods of a class or record in this way?



Something like the following pseudocode:



type
TMyRec = record
public
procedure DoSomething(x,y: integer) = ExternalMethod;









share|improve this question























  • Well, no. Ok, you can do what David proposes, but that only works if your first parameter is a pointer to such a record or if you can declare them as static class methods. But take care that you get the calling convention right too!

    – Rudy Velthuis
    Nov 16 '18 at 12:47











  • @rudy obviously you've got to match the parameter list, that goes without saying for external functions, but if this is a member function then clearly you will be passing the self pointer to it

    – David Heffernan
    Nov 16 '18 at 13:30













  • @david: yes but how? OK, if he himslef can add a self parameter to the functions, then fine, although a bit tricky. I personally would simply wrap the DLLfunctions and inline my wrappers.

    – Rudy Velthuis
    Nov 16 '18 at 15:43











  • It would be nice to know what the main parameter is. And does the default FPC Win32 calling convention match the one for Delphi?

    – Rudy Velthuis
    Nov 16 '18 at 15:46













  • @RudyVelthuis It looks like you don't understand the question. There are no DLLs, and since these are member functions the external code is clearly going to accept an instance pointer, because, well, member functions always do.

    – David Heffernan
    Nov 16 '18 at 15:46




















1















In Delphi I can link to external code like so:



   {$L 'C:UsersJohanDocumentsEmbarcaderoStudioProjectsLife64Lazaruslibx86_64-win64AVXGenerate.o'}

function GenerateQtoP_AVX_32(main, N,W,NW: pointer): byte;
external name 'AVXGENERATE_$$_GENERATEQTOP_AVX_32$POINTER$POINTER$POINTER$POINTER$$BYTE';
function GeneratePtoQ_AVX_32(main, S,E,SE: pointer): byte;
external name 'AVXGENERATE_$$_GENERATEPTOQ_AVX_32$POINTER$POINTER$POINTER$POINTER$$BYTE';
procedure ReverseBitsInAllBytes(ReverseMe: pointer);
external name 'AVXGENERATE_$$_REVERSEBITSINALLBYTES$POINTER';


In this case it links to AVX2 assembly code I write in Lazarus.



Is there a way to link member methods of a class or record in this way?



Something like the following pseudocode:



type
TMyRec = record
public
procedure DoSomething(x,y: integer) = ExternalMethod;









share|improve this question























  • Well, no. Ok, you can do what David proposes, but that only works if your first parameter is a pointer to such a record or if you can declare them as static class methods. But take care that you get the calling convention right too!

    – Rudy Velthuis
    Nov 16 '18 at 12:47











  • @rudy obviously you've got to match the parameter list, that goes without saying for external functions, but if this is a member function then clearly you will be passing the self pointer to it

    – David Heffernan
    Nov 16 '18 at 13:30













  • @david: yes but how? OK, if he himslef can add a self parameter to the functions, then fine, although a bit tricky. I personally would simply wrap the DLLfunctions and inline my wrappers.

    – Rudy Velthuis
    Nov 16 '18 at 15:43











  • It would be nice to know what the main parameter is. And does the default FPC Win32 calling convention match the one for Delphi?

    – Rudy Velthuis
    Nov 16 '18 at 15:46













  • @RudyVelthuis It looks like you don't understand the question. There are no DLLs, and since these are member functions the external code is clearly going to accept an instance pointer, because, well, member functions always do.

    – David Heffernan
    Nov 16 '18 at 15:46
















1












1








1








In Delphi I can link to external code like so:



   {$L 'C:UsersJohanDocumentsEmbarcaderoStudioProjectsLife64Lazaruslibx86_64-win64AVXGenerate.o'}

function GenerateQtoP_AVX_32(main, N,W,NW: pointer): byte;
external name 'AVXGENERATE_$$_GENERATEQTOP_AVX_32$POINTER$POINTER$POINTER$POINTER$$BYTE';
function GeneratePtoQ_AVX_32(main, S,E,SE: pointer): byte;
external name 'AVXGENERATE_$$_GENERATEPTOQ_AVX_32$POINTER$POINTER$POINTER$POINTER$$BYTE';
procedure ReverseBitsInAllBytes(ReverseMe: pointer);
external name 'AVXGENERATE_$$_REVERSEBITSINALLBYTES$POINTER';


In this case it links to AVX2 assembly code I write in Lazarus.



Is there a way to link member methods of a class or record in this way?



Something like the following pseudocode:



type
TMyRec = record
public
procedure DoSomething(x,y: integer) = ExternalMethod;









share|improve this question














In Delphi I can link to external code like so:



   {$L 'C:UsersJohanDocumentsEmbarcaderoStudioProjectsLife64Lazaruslibx86_64-win64AVXGenerate.o'}

function GenerateQtoP_AVX_32(main, N,W,NW: pointer): byte;
external name 'AVXGENERATE_$$_GENERATEQTOP_AVX_32$POINTER$POINTER$POINTER$POINTER$$BYTE';
function GeneratePtoQ_AVX_32(main, S,E,SE: pointer): byte;
external name 'AVXGENERATE_$$_GENERATEPTOQ_AVX_32$POINTER$POINTER$POINTER$POINTER$$BYTE';
procedure ReverseBitsInAllBytes(ReverseMe: pointer);
external name 'AVXGENERATE_$$_REVERSEBITSINALLBYTES$POINTER';


In this case it links to AVX2 assembly code I write in Lazarus.



Is there a way to link member methods of a class or record in this way?



Something like the following pseudocode:



type
TMyRec = record
public
procedure DoSomething(x,y: integer) = ExternalMethod;






delphi






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 16 '18 at 12:08









JohanJohan

61.1k19148260




61.1k19148260













  • Well, no. Ok, you can do what David proposes, but that only works if your first parameter is a pointer to such a record or if you can declare them as static class methods. But take care that you get the calling convention right too!

    – Rudy Velthuis
    Nov 16 '18 at 12:47











  • @rudy obviously you've got to match the parameter list, that goes without saying for external functions, but if this is a member function then clearly you will be passing the self pointer to it

    – David Heffernan
    Nov 16 '18 at 13:30













  • @david: yes but how? OK, if he himslef can add a self parameter to the functions, then fine, although a bit tricky. I personally would simply wrap the DLLfunctions and inline my wrappers.

    – Rudy Velthuis
    Nov 16 '18 at 15:43











  • It would be nice to know what the main parameter is. And does the default FPC Win32 calling convention match the one for Delphi?

    – Rudy Velthuis
    Nov 16 '18 at 15:46













  • @RudyVelthuis It looks like you don't understand the question. There are no DLLs, and since these are member functions the external code is clearly going to accept an instance pointer, because, well, member functions always do.

    – David Heffernan
    Nov 16 '18 at 15:46





















  • Well, no. Ok, you can do what David proposes, but that only works if your first parameter is a pointer to such a record or if you can declare them as static class methods. But take care that you get the calling convention right too!

    – Rudy Velthuis
    Nov 16 '18 at 12:47











  • @rudy obviously you've got to match the parameter list, that goes without saying for external functions, but if this is a member function then clearly you will be passing the self pointer to it

    – David Heffernan
    Nov 16 '18 at 13:30













  • @david: yes but how? OK, if he himslef can add a self parameter to the functions, then fine, although a bit tricky. I personally would simply wrap the DLLfunctions and inline my wrappers.

    – Rudy Velthuis
    Nov 16 '18 at 15:43











  • It would be nice to know what the main parameter is. And does the default FPC Win32 calling convention match the one for Delphi?

    – Rudy Velthuis
    Nov 16 '18 at 15:46













  • @RudyVelthuis It looks like you don't understand the question. There are no DLLs, and since these are member functions the external code is clearly going to accept an instance pointer, because, well, member functions always do.

    – David Heffernan
    Nov 16 '18 at 15:46



















Well, no. Ok, you can do what David proposes, but that only works if your first parameter is a pointer to such a record or if you can declare them as static class methods. But take care that you get the calling convention right too!

– Rudy Velthuis
Nov 16 '18 at 12:47





Well, no. Ok, you can do what David proposes, but that only works if your first parameter is a pointer to such a record or if you can declare them as static class methods. But take care that you get the calling convention right too!

– Rudy Velthuis
Nov 16 '18 at 12:47













@rudy obviously you've got to match the parameter list, that goes without saying for external functions, but if this is a member function then clearly you will be passing the self pointer to it

– David Heffernan
Nov 16 '18 at 13:30







@rudy obviously you've got to match the parameter list, that goes without saying for external functions, but if this is a member function then clearly you will be passing the self pointer to it

– David Heffernan
Nov 16 '18 at 13:30















@david: yes but how? OK, if he himslef can add a self parameter to the functions, then fine, although a bit tricky. I personally would simply wrap the DLLfunctions and inline my wrappers.

– Rudy Velthuis
Nov 16 '18 at 15:43





@david: yes but how? OK, if he himslef can add a self parameter to the functions, then fine, although a bit tricky. I personally would simply wrap the DLLfunctions and inline my wrappers.

– Rudy Velthuis
Nov 16 '18 at 15:43













It would be nice to know what the main parameter is. And does the default FPC Win32 calling convention match the one for Delphi?

– Rudy Velthuis
Nov 16 '18 at 15:46







It would be nice to know what the main parameter is. And does the default FPC Win32 calling convention match the one for Delphi?

– Rudy Velthuis
Nov 16 '18 at 15:46















@RudyVelthuis It looks like you don't understand the question. There are no DLLs, and since these are member functions the external code is clearly going to accept an instance pointer, because, well, member functions always do.

– David Heffernan
Nov 16 '18 at 15:46







@RudyVelthuis It looks like you don't understand the question. There are no DLLs, and since these are member functions the external code is clearly going to accept an instance pointer, because, well, member functions always do.

– David Heffernan
Nov 16 '18 at 15:46














1 Answer
1






active

oldest

votes


















3














It's not possible to do what you want. I think that perhaps the closest you can manage is to implement the method with an assembler jump to the external function:



type
TMyRec = record
public
procedure DoSomething(x, y: integer);
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
asm
JMP MyRecDoSomething
end;


Or you might make an inlined method:



type
TMyRec = record
public
procedure DoSomething(x, y: integer); inline;
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
begin
MyRecDoSomething(Self, x, y);
end;


When calling TMyRec.DoSomething, there is a call followed by a jump for the first version (using asm). For the second version (using inline) there is a single call directly to the external function.






share|improve this answer


























  • Note that the two approaches are not the same. If you inline, then the method that you inline, must have matching parameters between the inner and outer method or the output might get garbled. The jmp does not need any parameters.

    – Johan
    Nov 16 '18 at 14:15













  • That doesn't make any sense to me

    – David Heffernan
    Nov 16 '18 at 14:22











  • Still not making any sense to me. It sounds like you are talking about specifics of your code, and not the simplified version seen in this topic.

    – David Heffernan
    Nov 16 '18 at 14:53













  • Anyway, what you are saying isn't correct. The two variants offered here behave identically. There is a difference in that a call to TMyRec.DoSomething results in a call followed by a jump in the first version, and for the inlined version a call to TMyRec.DoSomething results in a direct call into the external function. Which is as efficient as possible I think.

    – David Heffernan
    Nov 16 '18 at 15:07











  • There is a bug in the compiler (Berlin). I'm trying to isolate it using a simple testcase.

    – Johan
    Nov 16 '18 at 15:23












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337621%2fcan-i-link-class-record-methods-to-an-external-module%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














It's not possible to do what you want. I think that perhaps the closest you can manage is to implement the method with an assembler jump to the external function:



type
TMyRec = record
public
procedure DoSomething(x, y: integer);
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
asm
JMP MyRecDoSomething
end;


Or you might make an inlined method:



type
TMyRec = record
public
procedure DoSomething(x, y: integer); inline;
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
begin
MyRecDoSomething(Self, x, y);
end;


When calling TMyRec.DoSomething, there is a call followed by a jump for the first version (using asm). For the second version (using inline) there is a single call directly to the external function.






share|improve this answer


























  • Note that the two approaches are not the same. If you inline, then the method that you inline, must have matching parameters between the inner and outer method or the output might get garbled. The jmp does not need any parameters.

    – Johan
    Nov 16 '18 at 14:15













  • That doesn't make any sense to me

    – David Heffernan
    Nov 16 '18 at 14:22











  • Still not making any sense to me. It sounds like you are talking about specifics of your code, and not the simplified version seen in this topic.

    – David Heffernan
    Nov 16 '18 at 14:53













  • Anyway, what you are saying isn't correct. The two variants offered here behave identically. There is a difference in that a call to TMyRec.DoSomething results in a call followed by a jump in the first version, and for the inlined version a call to TMyRec.DoSomething results in a direct call into the external function. Which is as efficient as possible I think.

    – David Heffernan
    Nov 16 '18 at 15:07











  • There is a bug in the compiler (Berlin). I'm trying to isolate it using a simple testcase.

    – Johan
    Nov 16 '18 at 15:23
















3














It's not possible to do what you want. I think that perhaps the closest you can manage is to implement the method with an assembler jump to the external function:



type
TMyRec = record
public
procedure DoSomething(x, y: integer);
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
asm
JMP MyRecDoSomething
end;


Or you might make an inlined method:



type
TMyRec = record
public
procedure DoSomething(x, y: integer); inline;
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
begin
MyRecDoSomething(Self, x, y);
end;


When calling TMyRec.DoSomething, there is a call followed by a jump for the first version (using asm). For the second version (using inline) there is a single call directly to the external function.






share|improve this answer


























  • Note that the two approaches are not the same. If you inline, then the method that you inline, must have matching parameters between the inner and outer method or the output might get garbled. The jmp does not need any parameters.

    – Johan
    Nov 16 '18 at 14:15













  • That doesn't make any sense to me

    – David Heffernan
    Nov 16 '18 at 14:22











  • Still not making any sense to me. It sounds like you are talking about specifics of your code, and not the simplified version seen in this topic.

    – David Heffernan
    Nov 16 '18 at 14:53













  • Anyway, what you are saying isn't correct. The two variants offered here behave identically. There is a difference in that a call to TMyRec.DoSomething results in a call followed by a jump in the first version, and for the inlined version a call to TMyRec.DoSomething results in a direct call into the external function. Which is as efficient as possible I think.

    – David Heffernan
    Nov 16 '18 at 15:07











  • There is a bug in the compiler (Berlin). I'm trying to isolate it using a simple testcase.

    – Johan
    Nov 16 '18 at 15:23














3












3








3







It's not possible to do what you want. I think that perhaps the closest you can manage is to implement the method with an assembler jump to the external function:



type
TMyRec = record
public
procedure DoSomething(x, y: integer);
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
asm
JMP MyRecDoSomething
end;


Or you might make an inlined method:



type
TMyRec = record
public
procedure DoSomething(x, y: integer); inline;
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
begin
MyRecDoSomething(Self, x, y);
end;


When calling TMyRec.DoSomething, there is a call followed by a jump for the first version (using asm). For the second version (using inline) there is a single call directly to the external function.






share|improve this answer















It's not possible to do what you want. I think that perhaps the closest you can manage is to implement the method with an assembler jump to the external function:



type
TMyRec = record
public
procedure DoSomething(x, y: integer);
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
asm
JMP MyRecDoSomething
end;


Or you might make an inlined method:



type
TMyRec = record
public
procedure DoSomething(x, y: integer); inline;
end;

procedure MyRecDoSomething(var Self: TMyRec; x, y: integer); external;

procedure TMyRec.DoSomething(x, y: integer);
begin
MyRecDoSomething(Self, x, y);
end;


When calling TMyRec.DoSomething, there is a call followed by a jump for the first version (using asm). For the second version (using inline) there is a single call directly to the external function.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 16 '18 at 15:09

























answered Nov 16 '18 at 12:28









David HeffernanDavid Heffernan

523k348361228




523k348361228













  • Note that the two approaches are not the same. If you inline, then the method that you inline, must have matching parameters between the inner and outer method or the output might get garbled. The jmp does not need any parameters.

    – Johan
    Nov 16 '18 at 14:15













  • That doesn't make any sense to me

    – David Heffernan
    Nov 16 '18 at 14:22











  • Still not making any sense to me. It sounds like you are talking about specifics of your code, and not the simplified version seen in this topic.

    – David Heffernan
    Nov 16 '18 at 14:53













  • Anyway, what you are saying isn't correct. The two variants offered here behave identically. There is a difference in that a call to TMyRec.DoSomething results in a call followed by a jump in the first version, and for the inlined version a call to TMyRec.DoSomething results in a direct call into the external function. Which is as efficient as possible I think.

    – David Heffernan
    Nov 16 '18 at 15:07











  • There is a bug in the compiler (Berlin). I'm trying to isolate it using a simple testcase.

    – Johan
    Nov 16 '18 at 15:23



















  • Note that the two approaches are not the same. If you inline, then the method that you inline, must have matching parameters between the inner and outer method or the output might get garbled. The jmp does not need any parameters.

    – Johan
    Nov 16 '18 at 14:15













  • That doesn't make any sense to me

    – David Heffernan
    Nov 16 '18 at 14:22











  • Still not making any sense to me. It sounds like you are talking about specifics of your code, and not the simplified version seen in this topic.

    – David Heffernan
    Nov 16 '18 at 14:53













  • Anyway, what you are saying isn't correct. The two variants offered here behave identically. There is a difference in that a call to TMyRec.DoSomething results in a call followed by a jump in the first version, and for the inlined version a call to TMyRec.DoSomething results in a direct call into the external function. Which is as efficient as possible I think.

    – David Heffernan
    Nov 16 '18 at 15:07











  • There is a bug in the compiler (Berlin). I'm trying to isolate it using a simple testcase.

    – Johan
    Nov 16 '18 at 15:23

















Note that the two approaches are not the same. If you inline, then the method that you inline, must have matching parameters between the inner and outer method or the output might get garbled. The jmp does not need any parameters.

– Johan
Nov 16 '18 at 14:15







Note that the two approaches are not the same. If you inline, then the method that you inline, must have matching parameters between the inner and outer method or the output might get garbled. The jmp does not need any parameters.

– Johan
Nov 16 '18 at 14:15















That doesn't make any sense to me

– David Heffernan
Nov 16 '18 at 14:22





That doesn't make any sense to me

– David Heffernan
Nov 16 '18 at 14:22













Still not making any sense to me. It sounds like you are talking about specifics of your code, and not the simplified version seen in this topic.

– David Heffernan
Nov 16 '18 at 14:53







Still not making any sense to me. It sounds like you are talking about specifics of your code, and not the simplified version seen in this topic.

– David Heffernan
Nov 16 '18 at 14:53















Anyway, what you are saying isn't correct. The two variants offered here behave identically. There is a difference in that a call to TMyRec.DoSomething results in a call followed by a jump in the first version, and for the inlined version a call to TMyRec.DoSomething results in a direct call into the external function. Which is as efficient as possible I think.

– David Heffernan
Nov 16 '18 at 15:07





Anyway, what you are saying isn't correct. The two variants offered here behave identically. There is a difference in that a call to TMyRec.DoSomething results in a call followed by a jump in the first version, and for the inlined version a call to TMyRec.DoSomething results in a direct call into the external function. Which is as efficient as possible I think.

– David Heffernan
Nov 16 '18 at 15:07













There is a bug in the compiler (Berlin). I'm trying to isolate it using a simple testcase.

– Johan
Nov 16 '18 at 15:23





There is a bug in the compiler (Berlin). I'm trying to isolate it using a simple testcase.

– Johan
Nov 16 '18 at 15:23




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337621%2fcan-i-link-class-record-methods-to-an-external-module%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Florida Star v. B. J. F.

Danny Elfman

Lugert, Oklahoma