Pascal as a library implementating language lazarus / 62-General ---------------------------------------------------------------------- JiaXing · 2020-05-06 14:57 I got this idea from cito: https://github.com/pfusik/cito QuoteĆ is not a general-purpose programming language. Instead, it is meant for implementing portable reusable libraries. Pascal is perfectly fit to be a library implementing language. But the problem is no one really exploit this aspect. There are many guides about how to flattern C++ library into plain C constructs but there is none for Object Pascal. How to flattern Object Pascal class into simple enough constructs so other languages could consume it? Is the principle the same as C++? We create and use an opaque record (empty record)? Example for C++: https://www.teddy.ch/c++_library_in_c/ I don't have any CS background so my using of words could be wrong. But the idea is just that. ---------------------------------------------------------------------- marcov · 2020-05-06 15:14 The general principles are the same as for C++. Mind your calling conventions, don't use automated types, and it will be fine. But the utility is limited, you get the same problem as with C++ flattening. As soon as you touch C++/FPC specific functionality or implementation details, the whole thing blows up. And FPC code often has a lot of methods/procedure with "string"  arguments. See e.g. the FreeBasic forum where there are some threads about wrapping the LCL for reuse. That requires method pointers, RTTI, properties, class types and heaps of other features. There are heaps of sources on linking various OO models of different languages to each other, and nearly all conclude it is hard, and what is possible is often only useful in specific cases. The only general solution is switching to a different shared object model (COM, GTK's glib and some variants and copies of those). But that often limits the languages features to the lowest common denominator and requires recoding. ---------------------------------------------------------------------- Thaddy · 2020-05-06 18:03 Opaque record is already implemented. ---------------------------------------------------------------------- Warfley · 2020-05-06 18:29 I always do it like this, internal I use classes, and I export functions that take a "handle" type, which basically is a raw pointer version of my classes. E.g. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i TFoo = class  procedure Bar;end; // Exported functionfunction do_bar(handle: Pointer): Boolean; cdecl;begin  Result := True;  try    TFoo(handle).Bar;  except    on E: Exception do      // handle exceptions  end;end; It's important that 1. memory you allocate in your library is freed in your library 2. managed types shall never leave your library (as this would skrew up reference counting) (i.e. no strings or arrays) 3. exceptions must be catched before leaving the library Also this could be mostly automated, using for example the code-tools package one could write an application that automatically provides a "flattened" version (like this above) for all the published fields of a class. I still do that by hand. Tedious but works. That way on the other end (e.g. in C++) I can write wrapper classes again: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i class Foo {private:  void *handle;public:  void bar() {    do_bar(handle);  }} ---------------------------------------------------------------------- marcov · 2020-05-06 18:38 You assume that exceptions are compatible. That is dangerous. Avoid exceptions in cross-language calls. ---------------------------------------------------------------------- Warfley · 2020-05-06 22:11 Quote from: marcov on May 06, 2020, 08:38:47 pmYou assume that exceptions are compatible. That is dangerous. Avoid exceptions in cross-language calls. Do you mean me? Thats exactly the reason why I catch the exceptions in the exported function. So any exception happening inside of the library will be catched before it returns. Also stated: Quote3. exceptions must be catched before leaving the library The exported functions should be the barrier where everything is converted from pascal internal to cross available (basically everything C-compatible) features ---------------------------------------------------------------------- PascalDragon · 2020-05-07 07:12 Quote from: marcov on May 06, 2020, 08:38:47 pmYou assume that exceptions are compatible. That is dangerous. Avoid exceptions in cross-language calls. Assuming the instance of TFoo was allocated in the library as well this won't be the case. What Warfley showed is that he catches any exceptions inside his library code before returning to (potentially) non-Pascal code. ---------------------------------------------------------------------- JiaXing · 2020-05-07 14:18 Quote from: PascalDragon on May 07, 2020, 09:12:35 amQuote from: marcov on May 06, 2020, 08:38:47 pmYou assume that exceptions are compatible. That is dangerous. Avoid exceptions in cross-language calls. Assuming the instance of TFoo was allocated in the library as well this won't be the case. What Warfley showed is that he catches any exceptions inside his library code before returning to (potentially) non-Pascal code. I don't know if Pascal exception works inside DLL but the C++ one is definitely not. One of the rule people told me when writting library (DLL) is to use error code but no exception is allowed. ---------------------------------------------------------------------- marcov · 2020-05-07 14:20 Quote from: Warfley on May 07, 2020, 12:11:16 amQuote from: marcov on May 06, 2020, 08:38:47 pmYou assume that exceptions are compatible. That is dangerous. Avoid exceptions in cross-language calls. Do you mean me? Thats exactly the reason why I catch the exceptions in the exported function. So any exception happening inside of the library will be catched before it returns. This is not always how it works when the exception systems are different. But luckily this will be less relevant in the future when FPC 3.2.0 moves to a SEH model on win32. ---------------------------------------------------------------------- JiaXing · 2020-05-07 14:24 Quote from: marcov on May 07, 2020, 04:20:40 pmQuote from: Warfley on May 07, 2020, 12:11:16 amQuote from: marcov on May 06, 2020, 08:38:47 pmYou assume that exceptions are compatible. That is dangerous. Avoid exceptions in cross-language calls. Do you mean me? Thats exactly the reason why I catch the exceptions in the exported function. So any exception happening inside of the library will be catched before it returns. This is not always how it works when the exception systems are different. But luckily this will be less relevant in the future when FPC 3.2.0 moves to a SEH model on win32. So it's all SJLJ before? ---------------------------------------------------------------------- PascalDragon · 2020-05-07 14:31 Quote from: JiaXing on May 07, 2020, 04:18:44 pmQuote from: PascalDragon on May 07, 2020, 09:12:35 amQuote from: marcov on May 06, 2020, 08:38:47 pmYou assume that exceptions are compatible. That is dangerous. Avoid exceptions in cross-language calls. Assuming the instance of TFoo was allocated in the library as well this won't be the case. What Warfley showed is that he catches any exceptions inside his library code before returning to (potentially) non-Pascal code. I don't know if Pascal exception works inside DLL but the C++ one is definitely not. One of the rule people told me when writting library (DLL) is to use error code but no exception is allowed. The topic isn't that clear cut. If you have an application and a DLL that are both compiled with MSVC and that use the C runtime as a dynamic library then you can use exceptions between them without problems. Thanks to Windows' Exception Handling mechanism it might even work if both (or one) uses the static C runtime. However cross language/compiler exceptions are much more problematic. If a library provides a C interfaces (in contrast to a C++ interface) then it's better not to let any exception travel out of the library and to use error codes instead. For example FPC with dynamic packages (which are nothing else than fancy DLLs) can use exceptions across package boundaries without any problems as well. If a FPC compiled statically compiled library comes into the mix however that library must not let exceptions travel outside of its scope. ---------------------------------------------------------------------- JiaXing · 2020-05-07 14:54 Quote from: PascalDragon on May 07, 2020, 04:31:40 pmQuote from: JiaXing on May 07, 2020, 04:18:44 pmQuote from: PascalDragon on May 07, 2020, 09:12:35 amQuote from: marcov on May 06, 2020, 08:38:47 pmYou assume that exceptions are compatible. That is dangerous. Avoid exceptions in cross-language calls. Assuming the instance of TFoo was allocated in the library as well this won't be the case. What Warfley showed is that he catches any exceptions inside his library code before returning to (potentially) non-Pascal code. I don't know if Pascal exception works inside DLL but the C++ one is definitely not. One of the rule people told me when writting library (DLL) is to use error code but no exception is allowed. The topic isn't that clear cut. If you have an application and a DLL that are both compiled with MSVC and that use the C runtime as a dynamic library then you can use exceptions between them without problems. Thanks to Windows' Exception Handling mechanism it might even work if both (or one) uses the static C runtime. However cross language/compiler exceptions are much more problematic. If a library provides a C interfaces (in contrast to a C++ interface) then it's better not to let any exception travel out of the library and to use error codes instead. For example FPC with dynamic packages (which are nothing else than fancy DLLs) can use exceptions across package boundaries without any problems as well. If a FPC compiled statically compiled library comes into the mix however that library must not let exceptions travel outside of its scope. I want to develop a library with advanced language features of Object Pascal (DLL1). Then I create a wrapper on Pascal, too (DLL2). This wrapper should exports C like constructs so other programming languages could consume it. And I will provide headers for each of these languages (bindings) for DLL2. As it's cross language, the discipline on C++ is never to use exception but only use error codes. And I don't know if the same discipline is viable on Pascal or not. It's just that. ---------------------------------------------------------------------- marcov · 2020-05-07 15:37 Quote from: JiaXing on May 07, 2020, 04:24:53 pmThis is not always how it works when the exception systems are different. But luckily this will be less relevant in the future when FPC 3.2.0 moves to a SEH model on win32. So it's all SJLJ before? [/quote] For win32, yes, _A_ SJLJ as pre principle. Not necessary an implementation of SJLJ that is compatible to any other SJLJ, just the general same idea.